summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2018-07-19 12:44:16 -0400
committerLuke Shumaker <lukeshu@lukeshu.com>2018-07-19 12:45:01 -0400
commitb11f5d09ce51a2cfa09c5765eea065174a0ce3af (patch)
tree33fa9308723eeb1f0a3c08af66bdcc75cc21dca2
parent52f5927b80febce2366e23fa4bce629e8df44efb (diff)
parent31e5d50f17d3993839d8f7c9f344a620e3871812 (diff)
Merge tag 'systemd/v239.0-2.parabola1' into systemd/parabolanotsystemd/v239.1-base
-rw-r--r--.github/ISSUE_TEMPLATE.md31
-rw-r--r--.github/ISSUE_TEMPLATE/Bug_report.md22
-rw-r--r--.github/ISSUE_TEMPLATE/Feature_request.md14
-rw-r--r--.mailmap10
-rw-r--r--.mkosi/mkosi.arch17
-rw-r--r--.mkosi/mkosi.debian17
-rw-r--r--.mkosi/mkosi.fedora18
-rw-r--r--.mkosi/mkosi.ubuntu72
-rw-r--r--.travis.yml123
-rw-r--r--NEWS384
-rw-r--r--README15
-rw-r--r--README.md3
-rw-r--r--TODO133
-rw-r--r--catalog/meson.build15
-rw-r--r--catalog/systemd.be.catalog.in18
-rw-r--r--catalog/systemd.be@latin.catalog.in18
-rw-r--r--catalog/systemd.bg.catalog.in18
-rw-r--r--catalog/systemd.catalog.in17
-rw-r--r--catalog/systemd.da.catalog.in17
-rw-r--r--catalog/systemd.de.catalog.in17
-rw-r--r--catalog/systemd.fr.catalog.in18
-rw-r--r--catalog/systemd.hr.catalog.in17
-rw-r--r--catalog/systemd.hu.catalog.in18
-rw-r--r--catalog/systemd.it.catalog.in17
-rw-r--r--catalog/systemd.ko.catalog.in17
-rw-r--r--catalog/systemd.pl.catalog.in18
-rw-r--r--catalog/systemd.pt_BR.catalog.in18
-rw-r--r--catalog/systemd.ru.catalog.in18
-rw-r--r--catalog/systemd.sr.catalog.in17
-rw-r--r--catalog/systemd.zh_CN.catalog.in18
-rw-r--r--catalog/systemd.zh_TW.catalog.in18
-rw-r--r--coccinelle/bool-cast.cocci12
-rw-r--r--coccinelle/div-round-up.cocci20
-rw-r--r--coccinelle/dup-fcntl.cocci5
-rw-r--r--coccinelle/empty-or-root.cocci10
-rw-r--r--coccinelle/flags-set.cocci15
-rw-r--r--coccinelle/o-ndelay.cocci (renamed from coccinelle/o-ndelay.occi)0
-rwxr-xr-xcoccinelle/run-coccinelle.sh29
-rw-r--r--coccinelle/take-fd.cocci14
-rw-r--r--coccinelle/take-ptr.cocci14
-rw-r--r--doc/BOOT_LOADER_SPECIFICATION.md140
-rw-r--r--doc/CGROUP_DELEGATION.md117
-rw-r--r--doc/CODE_QUALITY.md60
-rw-r--r--doc/CODING_STYLE50
-rw-r--r--doc/ENVIRONMENT.md7
-rw-r--r--doc/HACKING10
-rw-r--r--doc/PORTABLE_SERVICES.md251
-rw-r--r--doc/UIDS-GIDS.md2
-rw-r--r--doc/sysvinit/README.in (renamed from docs/sysvinit/README.in)0
-rw-r--r--doc/sysvinit/meson.build11
-rw-r--r--doc/var-log/README.in (renamed from docs/var-log/README.in)0
-rw-r--r--doc/var-log/meson.build11
-rw-r--r--docs/sysvinit/meson.build26
-rw-r--r--docs/var-log/meson.build26
-rw-r--r--hwdb/20-OUI.hwdb2333
-rw-r--r--hwdb/20-acpi-vendor.hwdb36
-rw-r--r--hwdb/20-acpi-vendor.hwdb.patch100
-rw-r--r--hwdb/20-pci-classes.hwdb35
-rw-r--r--hwdb/20-pci-vendor-model.hwdb1249
-rw-r--r--hwdb/20-usb-vendor-model.hwdb442
-rw-r--r--hwdb/20-vmbus-class.hwdb57
-rw-r--r--hwdb/60-evdev.hwdb18
-rw-r--r--hwdb/60-keyboard.hwdb20
-rw-r--r--hwdb/60-sensor.hwdb82
-rw-r--r--hwdb/70-mouse.hwdb7
-rw-r--r--hwdb/acpi_id_registry.html1
-rw-r--r--hwdb/ma-large.txt6837
-rw-r--r--hwdb/ma-medium.txt1490
-rw-r--r--hwdb/ma-small.txt1550
-rw-r--r--hwdb/meson.build16
-rwxr-xr-xhwdb/parse_hwdb.py5
-rw-r--r--hwdb/pci.ids480
-rw-r--r--hwdb/pnp_id_registry.html11
-rw-r--r--hwdb/usb.ids178
-rw-r--r--man/.dir-locals.el14
-rw-r--r--man/binfmt.d.xml34
-rw-r--r--man/bootctl.xml126
-rw-r--r--man/bootup.xml43
-rw-r--r--man/busctl.xml26
-rw-r--r--man/coredump.conf.xml36
-rw-r--r--man/coredumpctl.xml68
-rw-r--r--man/crypttab.xml33
-rw-r--r--man/custom-entities.ent.in3
-rw-r--r--man/custom-html.xsl16
-rw-r--r--man/custom-man.xsl17
-rw-r--r--man/daemon.xml26
-rw-r--r--man/dnssec-trust-anchors.d.xml26
-rw-r--r--man/environment.d.xml27
-rw-r--r--man/file-hierarchy.xml217
-rw-r--r--man/glib-event-glue.c64
-rw-r--r--man/halt.xml28
-rw-r--r--man/hostname.xml26
-rw-r--r--man/hostnamectl.xml26
-rw-r--r--man/hwdb.xml32
-rw-r--r--man/inotify-watch-tmp.c56
-rw-r--r--man/journal-iterate-poll.c25
-rw-r--r--man/journal-iterate-wait.c39
-rw-r--r--man/journal-remote.conf.xml36
-rw-r--r--man/journal-upload.conf.xml36
-rw-r--r--man/journalctl.xml60
-rw-r--r--man/journald.conf.xml48
-rw-r--r--man/kernel-command-line.xml26
-rw-r--r--man/kernel-install.xml28
-rw-r--r--man/less-variables.xml17
-rw-r--r--man/libsystemd-pkgconfig.xml17
-rw-r--r--man/libudev.xml26
-rw-r--r--man/loader.conf.xml185
-rw-r--r--man/locale.conf.xml26
-rw-r--r--man/localectl.xml35
-rw-r--r--man/localtime.xml33
-rw-r--r--man/loginctl.xml26
-rw-r--r--man/logind.conf.xml58
-rw-r--r--man/machine-id.xml30
-rw-r--r--man/machine-info.xml26
-rw-r--r--man/machinectl.xml37
-rw-r--r--man/meson.build15
-rw-r--r--man/modules-load.d.xml26
-rw-r--r--man/networkctl.xml28
-rw-r--r--man/networkd.conf.xml26
-rw-r--r--man/nss-myhostname.xml27
-rw-r--r--man/nss-mymachines.xml26
-rw-r--r--man/nss-resolve.xml27
-rw-r--r--man/nss-systemd.xml26
-rw-r--r--man/os-release.xml26
-rw-r--r--man/pam_systemd.xml83
-rw-r--r--man/portablectl.xml395
-rw-r--r--man/resolvectl.xml (renamed from man/systemd-resolve.xml)402
-rw-r--r--man/resolved.conf.xml58
-rw-r--r--man/rules/meson.build46
-rw-r--r--man/runlevel.xml26
-rw-r--r--man/sd-bus-errors.xml26
-rw-r--r--man/sd-bus.xml26
-rw-r--r--man/sd-daemon.xml26
-rw-r--r--man/sd-event.xml28
-rw-r--r--man/sd-id128.xml27
-rw-r--r--man/sd-journal.xml26
-rw-r--r--man/sd-login.xml26
-rw-r--r--man/sd_booted.xml26
-rw-r--r--man/sd_bus_add_match.xml34
-rw-r--r--man/sd_bus_creds_get_pid.xml39
-rw-r--r--man/sd_bus_creds_new_from_pid.xml39
-rw-r--r--man/sd_bus_default.xml74
-rw-r--r--man/sd_bus_error.xml38
-rw-r--r--man/sd_bus_error_add_map.xml26
-rw-r--r--man/sd_bus_get_fd.xml25
-rw-r--r--man/sd_bus_get_n_queued_read.xml26
-rw-r--r--man/sd_bus_is_open.xml26
-rw-r--r--man/sd_bus_message_append.xml36
-rw-r--r--man/sd_bus_message_append_array.xml36
-rw-r--r--man/sd_bus_message_append_basic.xml38
-rw-r--r--man/sd_bus_message_append_string_memfd.xml35
-rw-r--r--man/sd_bus_message_append_strv.xml36
-rw-r--r--man/sd_bus_message_get_cookie.xml40
-rw-r--r--man/sd_bus_message_get_monotonic_usec.xml42
-rw-r--r--man/sd_bus_message_read_basic.xml25
-rw-r--r--man/sd_bus_message_set_destination.xml39
-rw-r--r--man/sd_bus_negotiate_fds.xml38
-rw-r--r--man/sd_bus_new.xml38
-rw-r--r--man/sd_bus_path_encode.xml26
-rw-r--r--man/sd_bus_process.xml25
-rw-r--r--man/sd_bus_request_name.xml28
-rw-r--r--man/sd_bus_set_connected_signal.xml26
-rw-r--r--man/sd_bus_set_sender.xml26
-rw-r--r--man/sd_bus_set_watch_bind.xml26
-rw-r--r--man/sd_bus_slot_set_destroy_callback.xml131
-rw-r--r--man/sd_bus_slot_set_floating.xml118
-rw-r--r--man/sd_bus_track_add_name.xml36
-rw-r--r--man/sd_bus_track_new.xml36
-rw-r--r--man/sd_event_add_child.xml27
-rw-r--r--man/sd_event_add_defer.xml27
-rw-r--r--man/sd_event_add_inotify.xml191
-rw-r--r--man/sd_event_add_io.xml51
-rw-r--r--man/sd_event_add_signal.xml27
-rw-r--r--man/sd_event_add_time.xml27
-rw-r--r--man/sd_event_exit.xml26
-rw-r--r--man/sd_event_get_fd.xml26
-rw-r--r--man/sd_event_new.xml26
-rw-r--r--man/sd_event_now.xml26
-rw-r--r--man/sd_event_run.xml26
-rw-r--r--man/sd_event_set_watchdog.xml26
-rw-r--r--man/sd_event_source_get_event.xml26
-rw-r--r--man/sd_event_source_get_pending.xml26
-rw-r--r--man/sd_event_source_set_description.xml26
-rw-r--r--man/sd_event_source_set_destroy_callback.xml112
-rw-r--r--man/sd_event_source_set_enabled.xml26
-rw-r--r--man/sd_event_source_set_prepare.xml26
-rw-r--r--man/sd_event_source_set_priority.xml32
-rw-r--r--man/sd_event_source_set_userdata.xml26
-rw-r--r--man/sd_event_source_unref.xml26
-rw-r--r--man/sd_event_wait.xml26
-rw-r--r--man/sd_get_seats.xml43
-rw-r--r--man/sd_id128_get_machine.xml46
-rw-r--r--man/sd_id128_randomize.xml38
-rw-r--r--man/sd_id128_to_string.xml39
-rw-r--r--man/sd_is_fifo.xml26
-rw-r--r--man/sd_journal_add_match.xml45
-rw-r--r--man/sd_journal_enumerate_fields.xml33
-rw-r--r--man/sd_journal_get_catalog.xml36
-rw-r--r--man/sd_journal_get_cursor.xml35
-rw-r--r--man/sd_journal_get_cutoff_realtime_usec.xml36
-rw-r--r--man/sd_journal_get_data.xml43
-rw-r--r--man/sd_journal_get_fd.xml129
-rw-r--r--man/sd_journal_get_realtime_usec.xml40
-rw-r--r--man/sd_journal_get_usage.xml34
-rw-r--r--man/sd_journal_has_runtime_files.xml33
-rw-r--r--man/sd_journal_next.xml37
-rw-r--r--man/sd_journal_open.xml26
-rw-r--r--man/sd_journal_print.xml38
-rw-r--r--man/sd_journal_query_unique.xml36
-rw-r--r--man/sd_journal_seek_head.xml38
-rw-r--r--man/sd_journal_stream_fd.xml34
-rw-r--r--man/sd_listen_fds.xml26
-rw-r--r--man/sd_login_monitor_new.xml44
-rw-r--r--man/sd_machine_get_class.xml39
-rw-r--r--man/sd_notify.xml26
-rw-r--r--man/sd_pid_get_owner_uid.xml48
-rw-r--r--man/sd_seat_get_active.xml43
-rw-r--r--man/sd_session_is_active.xml49
-rw-r--r--man/sd_uid_get_state.xml38
-rw-r--r--man/sd_watchdog_enabled.xml26
-rw-r--r--man/shutdown.xml26
-rw-r--r--man/standard-conf.xml19
-rw-r--r--man/standard-options.xml26
-rw-r--r--man/sysctl.d.xml26
-rw-r--r--man/systemctl.xml92
-rw-r--r--man/systemd-analyze.xml78
-rw-r--r--man/systemd-ask-password-console.service.xml26
-rw-r--r--man/systemd-ask-password.xml34
-rw-r--r--man/systemd-backlight@.service.xml26
-rw-r--r--man/systemd-binfmt.service.xml38
-rw-r--r--man/systemd-boot.xml249
-rw-r--r--man/systemd-cat.xml26
-rw-r--r--man/systemd-cgls.xml26
-rw-r--r--man/systemd-cgtop.xml30
-rw-r--r--man/systemd-coredump.xml36
-rw-r--r--man/systemd-cryptsetup-generator.xml26
-rw-r--r--man/systemd-cryptsetup@.service.xml26
-rw-r--r--man/systemd-debug-generator.xml26
-rw-r--r--man/systemd-delta.xml26
-rw-r--r--man/systemd-detect-virt.xml32
-rw-r--r--man/systemd-environment-d-generator.xml26
-rw-r--r--man/systemd-escape.xml26
-rw-r--r--man/systemd-firstboot.xml26
-rw-r--r--man/systemd-fsck@.service.xml28
-rw-r--r--man/systemd-fstab-generator.xml26
-rw-r--r--man/systemd-getty-generator.xml26
-rw-r--r--man/systemd-gpt-auto-generator.xml79
-rw-r--r--man/systemd-halt.service.xml29
-rw-r--r--man/systemd-hibernate-resume-generator.xml26
-rw-r--r--man/systemd-hibernate-resume@.service.xml26
-rw-r--r--man/systemd-hostnamed.service.xml26
-rw-r--r--man/systemd-hwdb.xml38
-rw-r--r--man/systemd-importd.service.xml26
-rw-r--r--man/systemd-inhibit.xml29
-rw-r--r--man/systemd-initctl.service.xml26
-rw-r--r--man/systemd-journal-gatewayd.service.xml30
-rw-r--r--man/systemd-journal-remote.service.xml (renamed from man/systemd-journal-remote.xml)77
-rw-r--r--man/systemd-journal-upload.service.xml (renamed from man/systemd-journal-upload.xml)76
-rw-r--r--man/systemd-journald.service.xml52
-rw-r--r--man/systemd-localed.service.xml26
-rw-r--r--man/systemd-logind.service.xml26
-rw-r--r--man/systemd-machine-id-commit.service.xml26
-rw-r--r--man/systemd-machine-id-setup.xml32
-rw-r--r--man/systemd-machined.service.xml26
-rw-r--r--man/systemd-makefs@.service.xml28
-rw-r--r--man/systemd-modules-load.service.xml26
-rw-r--r--man/systemd-mount.xml28
-rw-r--r--man/systemd-networkd-wait-online.service.xml29
-rw-r--r--man/systemd-networkd.service.xml26
-rw-r--r--man/systemd-notify.xml26
-rw-r--r--man/systemd-nspawn.xml180
-rw-r--r--man/systemd-path.xml33
-rw-r--r--man/systemd-portabled.service.xml51
-rw-r--r--man/systemd-quotacheck.service.xml26
-rw-r--r--man/systemd-random-seed.service.xml26
-rw-r--r--man/systemd-rc-local-generator.xml26
-rw-r--r--man/systemd-remount-fs.service.xml26
-rw-r--r--man/systemd-resolved.service.xml84
-rw-r--r--man/systemd-rfkill.service.xml26
-rw-r--r--man/systemd-run.xml26
-rw-r--r--man/systemd-sleep.conf.xml64
-rw-r--r--man/systemd-socket-activate.xml26
-rw-r--r--man/systemd-socket-proxyd.xml29
-rw-r--r--man/systemd-suspend.service.xml44
-rw-r--r--man/systemd-sysctl.service.xml28
-rw-r--r--man/systemd-system-update-generator.xml26
-rw-r--r--man/systemd-system.conf.xml91
-rw-r--r--man/systemd-sysusers.xml28
-rw-r--r--man/systemd-sysv-generator.xml26
-rw-r--r--man/systemd-time-wait-sync.service.xml73
-rw-r--r--man/systemd-timedated.service.xml49
-rw-r--r--man/systemd-timesyncd.service.xml47
-rw-r--r--man/systemd-tmpfiles.xml30
-rw-r--r--man/systemd-tty-ask-password-agent.xml26
-rw-r--r--man/systemd-udevd.service.xml25
-rw-r--r--man/systemd-update-done.service.xml26
-rw-r--r--man/systemd-update-utmp.service.xml26
-rw-r--r--man/systemd-user-sessions.service.xml26
-rw-r--r--man/systemd-vconsole-setup.service.xml26
-rw-r--r--man/systemd-veritysetup-generator.xml26
-rw-r--r--man/systemd-veritysetup@.service.xml26
-rw-r--r--man/systemd-volatile-root.service.xml26
-rw-r--r--man/systemd.automount.xml66
-rw-r--r--man/systemd.device.xml57
-rw-r--r--man/systemd.dnssd.xml32
-rw-r--r--man/systemd.environment-generator.xml26
-rw-r--r--man/systemd.exec.xml299
-rw-r--r--man/systemd.generator.xml26
-rw-r--r--man/systemd.journal-fields.xml26
-rw-r--r--man/systemd.kill.xml26
-rw-r--r--man/systemd.link.xml64
-rw-r--r--man/systemd.mount.xml122
-rw-r--r--man/systemd.netdev.xml28
-rw-r--r--man/systemd.network.xml144
-rw-r--r--man/systemd.nspawn.xml115
-rw-r--r--man/systemd.offline-updates.xml39
-rw-r--r--man/systemd.path.xml76
-rw-r--r--man/systemd.preset.xml26
-rw-r--r--man/systemd.resource-control.xml26
-rw-r--r--man/systemd.scope.xml76
-rw-r--r--man/systemd.service.xml197
-rw-r--r--man/systemd.slice.xml66
-rw-r--r--man/systemd.socket.xml124
-rw-r--r--man/systemd.special.xml51
-rw-r--r--man/systemd.swap.xml86
-rw-r--r--man/systemd.syntax.xml98
-rw-r--r--man/systemd.target.xml78
-rw-r--r--man/systemd.time.xml26
-rw-r--r--man/systemd.timer.xml67
-rw-r--r--man/systemd.unit.xml344
-rw-r--r--man/systemd.xml82
-rw-r--r--man/sysusers.d.xml86
-rw-r--r--man/telinit.xml26
-rw-r--r--man/timedatectl.xml169
-rw-r--r--man/timesyncd.conf.xml32
-rw-r--r--man/tmpfiles.d.xml92
-rw-r--r--man/udev.conf.xml25
-rw-r--r--man/udev.xml33
-rw-r--r--man/udev_device_get_syspath.xml26
-rw-r--r--man/udev_device_has_tag.xml26
-rw-r--r--man/udev_device_new_from_syspath.xml26
-rw-r--r--man/udev_enumerate_add_match_subsystem.xml26
-rw-r--r--man/udev_enumerate_new.xml26
-rw-r--r--man/udev_enumerate_scan_devices.xml26
-rw-r--r--man/udev_list_entry.xml26
-rw-r--r--man/udev_monitor_filter_update.xml26
-rw-r--r--man/udev_monitor_new_from_netlink.xml26
-rw-r--r--man/udev_monitor_receive_device.xml26
-rw-r--r--man/udev_new.xml26
-rw-r--r--man/udevadm.xml46
-rw-r--r--man/user-system-options.xml18
-rw-r--r--man/vconsole.conf.xml26
-rw-r--r--meson.build556
-rw-r--r--meson_options.txt37
-rwxr-xr-xmkosi.build27
-rw-r--r--network/meson.build15
-rw-r--r--po/POTFILES.in1
-rw-r--r--po/be.po1
-rw-r--r--po/be@latin.po1
-rw-r--r--po/bg.po2
-rw-r--r--po/ca.po1
-rw-r--r--po/cs.po1
-rw-r--r--po/da.po1
-rw-r--r--po/de.po1
-rw-r--r--po/el.po1
-rw-r--r--po/es.po1
-rw-r--r--po/fr.po286
-rw-r--r--po/gl.po1
-rw-r--r--po/hr.po1
-rw-r--r--po/hu.po2
-rw-r--r--po/id.po1
-rw-r--r--po/ja.po70
-rw-r--r--po/ko.po1
-rw-r--r--po/meson.build15
-rw-r--r--po/pl.po285
-rw-r--r--po/pt_BR.po1
-rw-r--r--po/ro.po1
-rw-r--r--po/ru.po281
-rw-r--r--po/sk.po1
-rw-r--r--po/sr.po1
-rw-r--r--po/sv.po1
-rw-r--r--po/tr.po282
-rw-r--r--po/uk.po432
-rw-r--r--po/zh_CN.po1
-rw-r--r--po/zh_TW.po1
-rw-r--r--presets/meson.build15
-rw-r--r--rules/60-persistent-storage.rules2
-rw-r--r--rules/meson.build15
-rw-r--r--shell-completion/bash/bootctl1
-rw-r--r--shell-completion/bash/busctl22
-rw-r--r--shell-completion/bash/coredumpctl2
-rw-r--r--shell-completion/bash/hostnamectl2
-rw-r--r--shell-completion/bash/journalctl4
-rw-r--r--shell-completion/bash/kernel-install3
-rw-r--r--shell-completion/bash/localectl2
-rw-r--r--shell-completion/bash/loginctl2
-rw-r--r--shell-completion/bash/machinectl1
-rw-r--r--shell-completion/bash/meson.build17
-rw-r--r--shell-completion/bash/portablectl112
-rw-r--r--shell-completion/bash/resolvectl182
-rw-r--r--shell-completion/bash/systemctl.in100
-rw-r--r--shell-completion/bash/systemd-analyze29
-rw-r--r--shell-completion/bash/systemd-cat1
-rw-r--r--shell-completion/bash/systemd-cgls1
-rw-r--r--shell-completion/bash/systemd-cgtop1
-rw-r--r--shell-completion/bash/systemd-delta1
-rw-r--r--shell-completion/bash/systemd-detect-virt1
-rw-r--r--shell-completion/bash/systemd-nspawn1
-rw-r--r--shell-completion/bash/systemd-resolve5
-rw-r--r--shell-completion/bash/systemd-run2
-rw-r--r--shell-completion/bash/timedatectl7
-rw-r--r--shell-completion/bash/udevadm2
-rw-r--r--shell-completion/zsh/_busctl2
-rw-r--r--shell-completion/zsh/_sd_outputmodes2
-rw-r--r--shell-completion/zsh/_systemctl.in47
-rw-r--r--shell-completion/zsh/_systemd-resolve2
-rw-r--r--shell-completion/zsh/meson.build15
-rw-r--r--src/ac-power/ac-power.c88
-rw-r--r--src/activate/activate.c55
-rw-r--r--src/analyze/analyze-verify.c63
-rw-r--r--src/analyze/analyze-verify.h19
-rw-r--r--src/analyze/analyze.c301
-rw-r--r--src/analyze/meson.build15
-rw-r--r--src/ask-password/ask-password.c18
-rw-r--r--src/backlight/backlight.c94
-rw-r--r--src/basic/MurmurHash2.c2
-rw-r--r--src/basic/MurmurHash2.h2
-rw-r--r--src/basic/af-list.c18
-rw-r--r--src/basic/af-list.h19
-rw-r--r--src/basic/alloc-util.c18
-rw-r--r--src/basic/alloc-util.h40
-rw-r--r--src/basic/architecture.c18
-rw-r--r--src/basic/architecture.h19
-rw-r--r--src/basic/arphrd-list.c18
-rw-r--r--src/basic/arphrd-list.h19
-rw-r--r--src/basic/async.c18
-rw-r--r--src/basic/async.h19
-rw-r--r--src/basic/audit-util.c18
-rw-r--r--src/basic/audit-util.h19
-rw-r--r--src/basic/barrier.c18
-rw-r--r--src/basic/barrier.h18
-rw-r--r--src/basic/bitmap.c18
-rw-r--r--src/basic/bitmap.h18
-rw-r--r--src/basic/blkid-util.h20
-rw-r--r--src/basic/blockdev-util.c84
-rw-r--r--src/basic/blockdev-util.h20
-rw-r--r--src/basic/bpf-program.c22
-rw-r--r--src/basic/bpf-program.h21
-rw-r--r--src/basic/btrfs-util.c27
-rw-r--r--src/basic/btrfs-util.h19
-rw-r--r--src/basic/build.h19
-rw-r--r--src/basic/bus-label.c18
-rw-r--r--src/basic/bus-label.h19
-rw-r--r--src/basic/calendarspec.c152
-rw-r--r--src/basic/calendarspec.h19
-rw-r--r--src/basic/cap-list.c21
-rw-r--r--src/basic/cap-list.h19
-rw-r--r--src/basic/capability-util.c37
-rw-r--r--src/basic/capability-util.h21
-rw-r--r--src/basic/cgroup-util.c73
-rw-r--r--src/basic/cgroup-util.h19
-rw-r--r--src/basic/chattr-util.c18
-rw-r--r--src/basic/chattr-util.h19
-rw-r--r--src/basic/clock-util.c18
-rw-r--r--src/basic/clock-util.h19
-rw-r--r--src/basic/conf-files.c216
-rw-r--r--src/basic/conf-files.h32
-rw-r--r--src/basic/copy.c339
-rw-r--r--src/basic/copy.h31
-rw-r--r--src/basic/cpu-set-util.c24
-rw-r--r--src/basic/cpu-set-util.h18
-rw-r--r--src/basic/crypt-util.c19
-rw-r--r--src/basic/crypt-util.h18
-rw-r--r--src/basic/def.h33
-rw-r--r--src/basic/device-nodes.c18
-rw-r--r--src/basic/device-nodes.h19
-rw-r--r--src/basic/dirent-util.c18
-rw-r--r--src/basic/dirent-util.h19
-rw-r--r--src/basic/env-util.c49
-rw-r--r--src/basic/env-util.h23
-rw-r--r--src/basic/errno-list.c18
-rw-r--r--src/basic/errno-list.h19
-rw-r--r--src/basic/escape.c28
-rw-r--r--src/basic/escape.h21
-rw-r--r--src/basic/ether-addr-util.c60
-rw-r--r--src/basic/ether-addr-util.h29
-rw-r--r--src/basic/exec-util.c22
-rw-r--r--src/basic/exec-util.h18
-rw-r--r--src/basic/exit-status.c98
-rw-r--r--src/basic/exit-status.h27
-rw-r--r--src/basic/extract-word.c21
-rw-r--r--src/basic/extract-word.h19
-rw-r--r--src/basic/fd-util.c302
-rw-r--r--src/basic/fd-util.h37
-rw-r--r--src/basic/fileio-label.c18
-rw-r--r--src/basic/fileio-label.h18
-rw-r--r--src/basic/fileio.c211
-rw-r--r--src/basic/fileio.h36
-rw-r--r--src/basic/format-table.c1247
-rw-r--r--src/basic/format-table.h62
-rw-r--r--src/basic/format-util.h18
-rw-r--r--src/basic/fs-util.c291
-rw-r--r--src/basic/fs-util.h42
-rw-r--r--src/basic/gcrypt-util.c20
-rw-r--r--src/basic/gcrypt-util.h20
-rw-r--r--src/basic/glob-util.c18
-rw-r--r--src/basic/glob-util.h19
-rw-r--r--src/basic/gunicode.c2
-rw-r--r--src/basic/gunicode.h2
-rw-r--r--src/basic/hash-funcs.c20
-rw-r--r--src/basic/hash-funcs.h19
-rw-r--r--src/basic/hashmap.c21
-rw-r--r--src/basic/hashmap.h19
-rw-r--r--src/basic/hexdecoct.c105
-rw-r--r--src/basic/hexdecoct.h19
-rw-r--r--src/basic/hostname-util.c18
-rw-r--r--src/basic/hostname-util.h19
-rw-r--r--src/basic/in-addr-util.c18
-rw-r--r--src/basic/in-addr-util.h19
-rw-r--r--src/basic/io-util.c18
-rw-r--r--src/basic/io-util.h28
-rw-r--r--src/basic/ioprio.h5
-rw-r--r--src/basic/journal-importer.c124
-rw-r--r--src/basic/journal-importer.h21
-rw-r--r--src/basic/khash.c21
-rw-r--r--src/basic/khash.h19
-rw-r--r--src/basic/label.c28
-rw-r--r--src/basic/label.h26
-rw-r--r--src/basic/list.h19
-rw-r--r--src/basic/locale-util.c39
-rw-r--r--src/basic/locale-util.h20
-rw-r--r--src/basic/lockfile-util.c18
-rw-r--r--src/basic/lockfile-util.h21
-rw-r--r--src/basic/log.c45
-rw-r--r--src/basic/log.h23
-rw-r--r--src/basic/login-util.c18
-rw-r--r--src/basic/login-util.h19
-rw-r--r--src/basic/macro.h37
-rw-r--r--src/basic/memfd-util.c23
-rw-r--r--src/basic/memfd-util.h19
-rw-r--r--src/basic/mempool.c30
-rw-r--r--src/basic/mempool.h22
-rw-r--r--src/basic/meson.build28
-rw-r--r--src/basic/missing.h35
-rw-r--r--src/basic/missing_syscall.h21
-rw-r--r--src/basic/mkdir-label.c25
-rw-r--r--src/basic/mkdir.c58
-rw-r--r--src/basic/mkdir.h30
-rw-r--r--src/basic/module-util.h19
-rw-r--r--src/basic/mount-util.c47
-rw-r--r--src/basic/mount-util.h19
-rw-r--r--src/basic/nss-util.h25
-rw-r--r--src/basic/ordered-set.c18
-rw-r--r--src/basic/ordered-set.h27
-rw-r--r--src/basic/os-util.c117
-rw-r--r--src/basic/os-util.h12
-rw-r--r--src/basic/pager.c (renamed from src/shared/pager.c)18
-rw-r--r--src/basic/pager.h12
-rw-r--r--src/basic/parse-util.c150
-rw-r--r--src/basic/parse-util.h45
-rw-r--r--src/basic/path-util.c253
-rw-r--r--src/basic/path-util.h61
-rw-r--r--src/basic/prioq.c18
-rw-r--r--src/basic/prioq.h19
-rw-r--r--src/basic/proc-cmdline.c24
-rw-r--r--src/basic/proc-cmdline.h19
-rw-r--r--src/basic/process-util.c94
-rw-r--r--src/basic/process-util.h52
-rw-r--r--src/basic/random-util.c23
-rw-r--r--src/basic/random-util.h19
-rw-r--r--src/basic/ratelimit.c21
-rw-r--r--src/basic/ratelimit.h21
-rw-r--r--src/basic/raw-clone.h43
-rw-r--r--src/basic/reboot-util.h6
-rw-r--r--src/basic/refcnt.h19
-rw-r--r--src/basic/replace-var.c18
-rw-r--r--src/basic/replace-var.h19
-rw-r--r--src/basic/rlimit-util.c107
-rw-r--r--src/basic/rlimit-util.h23
-rw-r--r--src/basic/rm-rf.c40
-rw-r--r--src/basic/rm-rf.h19
-rw-r--r--src/basic/securebits-util.c21
-rw-r--r--src/basic/securebits-util.h18
-rw-r--r--src/basic/selinux-util.c99
-rw-r--r--src/basic/selinux-util.h22
-rw-r--r--src/basic/set.c62
-rw-r--r--src/basic/set.h21
-rw-r--r--src/basic/sigbus.c18
-rw-r--r--src/basic/sigbus.h19
-rw-r--r--src/basic/signal-util.c89
-rw-r--r--src/basic/signal-util.h21
-rw-r--r--src/basic/smack-util.c107
-rw-r--r--src/basic/smack-util.h32
-rw-r--r--src/basic/socket-label.c18
-rw-r--r--src/basic/socket-protocol-list.c18
-rw-r--r--src/basic/socket-protocol-list.h19
-rw-r--r--src/basic/socket-util.c30
-rw-r--r--src/basic/socket-util.h21
-rw-r--r--src/basic/special.h20
-rw-r--r--src/basic/stat-util.c44
-rw-r--r--src/basic/stat-util.h20
-rw-r--r--src/basic/stdio-util.h19
-rw-r--r--src/basic/strbuf.c83
-rw-r--r--src/basic/strbuf.h21
-rw-r--r--src/basic/string-table.c18
-rw-r--r--src/basic/string-table.h44
-rw-r--r--src/basic/string-util.c303
-rw-r--r--src/basic/string-util.h50
-rw-r--r--src/basic/strv.c58
-rw-r--r--src/basic/strv.h25
-rw-r--r--src/basic/strxcpyx.c18
-rw-r--r--src/basic/strxcpyx.h19
-rw-r--r--src/basic/syslog-util.c18
-rw-r--r--src/basic/syslog-util.h19
-rw-r--r--src/basic/terminal-util.c235
-rw-r--r--src/basic/terminal-util.h46
-rw-r--r--src/basic/time-util.c116
-rw-r--r--src/basic/time-util.h25
-rw-r--r--src/basic/umask-util.h19
-rw-r--r--src/basic/unaligned.h18
-rw-r--r--src/basic/unit-def.c19
-rw-r--r--src/basic/unit-def.h24
-rw-r--r--src/basic/unit-name.c99
-rw-r--r--src/basic/unit-name.h30
-rw-r--r--src/basic/user-util.c129
-rw-r--r--src/basic/user-util.h34
-rw-r--r--src/basic/utf8.c58
-rw-r--r--src/basic/utf8.h21
-rw-r--r--src/basic/util.c78
-rw-r--r--src/basic/util.h48
-rw-r--r--src/basic/verbs.c20
-rw-r--r--src/basic/verbs.h19
-rw-r--r--src/basic/virt.c100
-rw-r--r--src/basic/virt.h19
-rw-r--r--src/basic/web-util.c18
-rw-r--r--src/basic/web-util.h19
-rw-r--r--src/basic/xattr-util.c18
-rw-r--r--src/basic/xattr-util.h19
-rw-r--r--src/basic/xml.c18
-rw-r--r--src/basic/xml.h19
-rw-r--r--src/binfmt/binfmt.c59
-rw-r--r--src/boot/bootctl.c23
-rw-r--r--src/boot/efi/boot.c448
-rw-r--r--src/boot/efi/console.c118
-rw-r--r--src/boot/efi/console.h21
-rw-r--r--src/boot/efi/disk.c23
-rw-r--r--src/boot/efi/disk.h13
-rw-r--r--src/boot/efi/graphics.c15
-rw-r--r--src/boot/efi/graphics.h15
-rw-r--r--src/boot/efi/linux.c15
-rw-r--r--src/boot/efi/linux.h13
-rw-r--r--src/boot/efi/measure.c11
-rw-r--r--src/boot/efi/measure.h10
-rw-r--r--src/boot/efi/meson.build15
-rw-r--r--src/boot/efi/pe.c21
-rw-r--r--src/boot/efi/pe.h13
-rw-r--r--src/boot/efi/shim.c49
-rw-r--r--src/boot/efi/shim.h14
-rw-r--r--src/boot/efi/splash.c32
-rw-r--r--src/boot/efi/splash.h13
-rw-r--r--src/boot/efi/stub.c37
-rw-r--r--src/boot/efi/util.c65
-rw-r--r--src/boot/efi/util.h22
-rw-r--r--src/busctl/busctl-introspect.c26
-rw-r--r--src/busctl/busctl-introspect.h19
-rw-r--r--src/busctl/busctl.c542
-rw-r--r--src/cgls/cgls.c30
-rw-r--r--src/cgroups-agent/cgroups-agent.c18
-rw-r--r--src/cgtop/cgtop.c34
-rw-r--r--src/core/all-units.h14
-rw-r--r--src/core/audit-fd.c19
-rw-r--r--src/core/audit-fd.h19
-rw-r--r--src/core/automount.c32
-rw-r--r--src/core/automount.h21
-rw-r--r--src/core/bpf-firewall.c27
-rw-r--r--src/core/bpf-firewall.h18
-rw-r--r--src/core/cgroup.c140
-rw-r--r--src/core/cgroup.h22
-rw-r--r--src/core/chown-recursive.c18
-rw-r--r--src/core/chown-recursive.h19
-rw-r--r--src/core/dbus-automount.c18
-rw-r--r--src/core/dbus-automount.h21
-rw-r--r--src/core/dbus-cgroup.c195
-rw-r--r--src/core/dbus-cgroup.h21
-rw-r--r--src/core/dbus-device.c18
-rw-r--r--src/core/dbus-device.h21
-rw-r--r--src/core/dbus-execute.c391
-rw-r--r--src/core/dbus-execute.h20
-rw-r--r--src/core/dbus-job.c21
-rw-r--r--src/core/dbus-job.h20
-rw-r--r--src/core/dbus-kill.c18
-rw-r--r--src/core/dbus-kill.h20
-rw-r--r--src/core/dbus-manager.c340
-rw-r--r--src/core/dbus-manager.h19
-rw-r--r--src/core/dbus-mount.c101
-rw-r--r--src/core/dbus-mount.h20
-rw-r--r--src/core/dbus-path.c45
-rw-r--r--src/core/dbus-path.h20
-rw-r--r--src/core/dbus-scope.c18
-rw-r--r--src/core/dbus-scope.h21
-rw-r--r--src/core/dbus-service.c27
-rw-r--r--src/core/dbus-service.h20
-rw-r--r--src/core/dbus-slice.c18
-rw-r--r--src/core/dbus-slice.h20
-rw-r--r--src/core/dbus-socket.c55
-rw-r--r--src/core/dbus-socket.h20
-rw-r--r--src/core/dbus-swap.c74
-rw-r--r--src/core/dbus-swap.h19
-rw-r--r--src/core/dbus-target.c18
-rw-r--r--src/core/dbus-target.h21
-rw-r--r--src/core/dbus-timer.c46
-rw-r--r--src/core/dbus-timer.h20
-rw-r--r--src/core/dbus-unit.c316
-rw-r--r--src/core/dbus-unit.h23
-rw-r--r--src/core/dbus-util.c38
-rw-r--r--src/core/dbus-util.h123
-rw-r--r--src/core/dbus.c95
-rw-r--r--src/core/dbus.h21
-rw-r--r--src/core/device.c543
-rw-r--r--src/core/device.h46
-rw-r--r--src/core/dynamic-user.c31
-rw-r--r--src/core/dynamic-user.h20
-rw-r--r--src/core/emergency-action.c18
-rw-r--r--src/core/emergency-action.h18
-rw-r--r--src/core/execute.c336
-rw-r--r--src/core/execute.h56
-rw-r--r--src/core/hostname-setup.c18
-rw-r--r--src/core/hostname-setup.h19
-rw-r--r--src/core/ima-setup.c20
-rw-r--r--src/core/ima-setup.h20
-rw-r--r--src/core/ip-address-access.c18
-rw-r--r--src/core/ip-address-access.h21
-rw-r--r--src/core/job.c88
-rw-r--r--src/core/job.h22
-rw-r--r--src/core/kill.c18
-rw-r--r--src/core/kill.h19
-rw-r--r--src/core/killall.c18
-rw-r--r--src/core/killall.h19
-rw-r--r--src/core/kmod-setup.c18
-rw-r--r--src/core/kmod-setup.h19
-rw-r--r--src/core/load-dropin.c47
-rw-r--r--src/core/load-dropin.h21
-rw-r--r--src/core/load-fragment-gperf.gperf.m459
-rw-r--r--src/core/load-fragment.c1506
-rw-r--r--src/core/load-fragment.h215
-rw-r--r--src/core/locale-setup.c25
-rw-r--r--src/core/locale-setup.h19
-rw-r--r--src/core/loopback-setup.c18
-rw-r--r--src/core/loopback-setup.h19
-rw-r--r--src/core/machine-id-setup.c18
-rw-r--r--src/core/machine-id-setup.h19
-rw-r--r--src/core/macros.systemd.in46
-rw-r--r--src/core/main.c338
-rw-r--r--src/core/manager.c646
-rw-r--r--src/core/manager.h55
-rw-r--r--src/core/meson.build20
-rw-r--r--src/core/mount-setup.c69
-rw-r--r--src/core/mount-setup.h19
-rw-r--r--src/core/mount.c58
-rw-r--r--src/core/mount.h22
-rw-r--r--src/core/namespace.c368
-rw-r--r--src/core/namespace.h33
-rw-r--r--src/core/org.freedesktop.systemd1.conf12
-rw-r--r--src/core/org.freedesktop.systemd1.policy.in1
-rw-r--r--src/core/path.c24
-rw-r--r--src/core/path.h21
-rw-r--r--src/core/scope.c59
-rw-r--r--src/core/scope.h21
-rw-r--r--src/core/selinux-access.c17
-rw-r--r--src/core/selinux-access.h17
-rw-r--r--src/core/selinux-setup.c24
-rw-r--r--src/core/selinux-setup.h19
-rw-r--r--src/core/service.c135
-rw-r--r--src/core/service.h25
-rw-r--r--src/core/show-status.c18
-rw-r--r--src/core/show-status.h19
-rw-r--r--src/core/shutdown.c38
-rw-r--r--src/core/slice.c28
-rw-r--r--src/core/slice.h21
-rw-r--r--src/core/smack-setup.c17
-rw-r--r--src/core/smack-setup.h17
-rw-r--r--src/core/socket.c171
-rw-r--r--src/core/socket.h25
-rw-r--r--src/core/swap.c66
-rw-r--r--src/core/swap.h21
-rw-r--r--src/core/system.conf.in1
-rw-r--r--src/core/target.c20
-rw-r--r--src/core/target.h21
-rw-r--r--src/core/timer.c35
-rw-r--r--src/core/timer.h22
-rw-r--r--src/core/transaction.c31
-rw-r--r--src/core/transaction.h19
-rw-r--r--src/core/triggers.systemd.in17
-rw-r--r--src/core/umount.c293
-rw-r--r--src/core/umount.h33
-rw-r--r--src/core/unit-printf.c108
-rw-r--r--src/core/unit-printf.h19
-rw-r--r--src/core/unit.c316
-rw-r--r--src/core/unit.h113
-rw-r--r--src/coredump/coredump-vacuum.c21
-rw-r--r--src/coredump/coredump-vacuum.h19
-rw-r--r--src/coredump/coredump.c74
-rw-r--r--src/coredump/coredumpctl.c288
-rw-r--r--src/coredump/meson.build15
-rw-r--r--src/coredump/stacktrace.c21
-rw-r--r--src/coredump/stacktrace.h19
-rw-r--r--src/coredump/test-coredump-vacuum.c18
-rw-r--r--src/cryptsetup/cryptsetup-generator.c19
-rw-r--r--src/cryptsetup/cryptsetup.c21
-rw-r--r--src/debug-generator/debug-generator.c22
-rw-r--r--src/delta/delta.c33
-rw-r--r--src/detect-virt/detect-virt.c26
-rw-r--r--src/dissect/dissect.c44
-rw-r--r--src/environment-d-generator/environment-d-generator.c21
-rw-r--r--src/escape/escape.c19
-rw-r--r--src/firstboot/firstboot.c64
-rw-r--r--src/fsck/fsck.c18
-rw-r--r--src/fstab-generator/fstab-generator.c22
-rw-r--r--src/fuzz/fuzz-dhcp-server.c16
-rw-r--r--src/fuzz/fuzz-dhcp-server.options (renamed from src/fuzz/fuzz-dns-server.options)0
-rw-r--r--src/fuzz/fuzz-dns-packet.c16
-rw-r--r--src/fuzz/fuzz-journal-remote.c75
-rw-r--r--src/fuzz/fuzz-journal-remote.options2
-rw-r--r--src/fuzz/fuzz-main.c20
-rw-r--r--src/fuzz/fuzz-unit-file.c84
-rw-r--r--src/fuzz/fuzz.h16
-rw-r--r--src/fuzz/meson.build30
-rw-r--r--src/getty-generator/getty-generator.c18
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c91
-rw-r--r--src/hibernate-resume/hibernate-resume-generator.c18
-rw-r--r--src/hibernate-resume/hibernate-resume.c18
-rw-r--r--src/hostname/hostnamectl.c231
-rw-r--r--src/hostname/hostnamed.c121
-rw-r--r--src/hostname/meson.build15
-rw-r--r--src/hostname/org.freedesktop.hostname1.policy2
-rw-r--r--src/hostname/org.freedesktop.hostname1.service2
-rw-r--r--src/hwdb/hwdb.c95
-rw-r--r--src/import/curl-util.c36
-rw-r--r--src/import/curl-util.h19
-rw-r--r--src/import/export-raw.c34
-rw-r--r--src/import/export-raw.h19
-rw-r--r--src/import/export-tar.c23
-rw-r--r--src/import/export-tar.h19
-rw-r--r--src/import/export.c34
-rw-r--r--src/import/import-common.c30
-rw-r--r--src/import/import-common.h19
-rw-r--r--src/import/import-compress.c18
-rw-r--r--src/import/import-compress.h19
-rw-r--r--src/import/import-raw.c26
-rw-r--r--src/import/import-raw.h19
-rw-r--r--src/import/import-tar.c23
-rw-r--r--src/import/import-tar.h19
-rw-r--r--src/import/import.c36
-rw-r--r--src/import/importd.c30
-rw-r--r--src/import/meson.build15
-rw-r--r--src/import/pull-common.c24
-rw-r--r--src/import/pull-common.h19
-rw-r--r--src/import/pull-job.c21
-rw-r--r--src/import/pull-job.h19
-rw-r--r--src/import/pull-raw.c24
-rw-r--r--src/import/pull-raw.h19
-rw-r--r--src/import/pull-tar.c21
-rw-r--r--src/import/pull-tar.h19
-rw-r--r--src/import/pull.c36
-rw-r--r--src/import/qcow2-util.c18
-rw-r--r--src/import/qcow2-util.h19
-rw-r--r--src/import/test-qcow2.c18
-rw-r--r--src/initctl/initctl.c18
-rw-r--r--src/journal-remote/journal-gatewayd.c28
-rw-r--r--src/journal-remote/journal-remote-main.c1145
-rw-r--r--src/journal-remote/journal-remote-parse.c24
-rw-r--r--src/journal-remote/journal-remote-parse.h19
-rw-r--r--src/journal-remote/journal-remote-write.c33
-rw-r--r--src/journal-remote/journal-remote-write.h20
-rw-r--r--src/journal-remote/journal-remote.c1246
-rw-r--r--src/journal-remote/journal-remote.h51
-rw-r--r--src/journal-remote/journal-upload-journal.c30
-rw-r--r--src/journal-remote/journal-upload.c22
-rwxr-xr-xsrc/journal-remote/log-generator.py7
-rw-r--r--src/journal-remote/meson.build41
-rw-r--r--src/journal-remote/microhttpd-util.c26
-rw-r--r--src/journal-remote/microhttpd-util.h19
-rw-r--r--src/journal/audit-type.c18
-rw-r--r--src/journal/audit-type.h19
-rw-r--r--src/journal/cat.c18
-rw-r--r--src/journal/catalog.c74
-rw-r--r--src/journal/catalog.h19
-rw-r--r--src/journal/compress.c20
-rw-r--r--src/journal/compress.h19
-rw-r--r--src/journal/fsprg.c2
-rw-r--r--src/journal/fsprg.h2
-rw-r--r--src/journal/journal-authenticate.c18
-rw-r--r--src/journal/journal-authenticate.h19
-rw-r--r--src/journal/journal-def.h19
-rw-r--r--src/journal/journal-file.c113
-rw-r--r--src/journal/journal-file.h37
-rw-r--r--src/journal/journal-internal.h19
-rw-r--r--src/journal/journal-qrcode.c18
-rw-r--r--src/journal/journal-qrcode.h19
-rw-r--r--src/journal/journal-send.c24
-rw-r--r--src/journal/journal-vacuum.c21
-rw-r--r--src/journal/journal-vacuum.h19
-rw-r--r--src/journal/journal-verify.c18
-rw-r--r--src/journal/journal-verify.h19
-rw-r--r--src/journal/journalctl.c92
-rw-r--r--src/journal/journald-audit.c29
-rw-r--r--src/journal/journald-audit.h19
-rw-r--r--src/journal/journald-console.c18
-rw-r--r--src/journal/journald-console.h19
-rw-r--r--src/journal/journald-context.c25
-rw-r--r--src/journal/journald-context.h19
-rw-r--r--src/journal/journald-gperf.gperf2
-rw-r--r--src/journal/journald-kmsg.c18
-rw-r--r--src/journal/journald-kmsg.h19
-rw-r--r--src/journal/journald-native.c29
-rw-r--r--src/journal/journald-native.h42
-rw-r--r--src/journal/journald-rate-limit.c18
-rw-r--r--src/journal/journald-rate-limit.h19
-rw-r--r--src/journal/journald-server.c85
-rw-r--r--src/journal/journald-server.h34
-rw-r--r--src/journal/journald-stream.c32
-rw-r--r--src/journal/journald-stream.h19
-rw-r--r--src/journal/journald-syslog.c55
-rw-r--r--src/journal/journald-syslog.h21
-rw-r--r--src/journal/journald-wall.c17
-rw-r--r--src/journal/journald-wall.h17
-rw-r--r--src/journal/journald.c18
-rw-r--r--src/journal/journald.conf2
-rw-r--r--src/journal/lookup3.c20
-rw-r--r--src/journal/meson.build15
-rw-r--r--src/journal/mmap-cache.c21
-rw-r--r--src/journal/mmap-cache.h19
-rw-r--r--src/journal/sd-journal.c92
-rw-r--r--src/journal/test-audit-type.c18
-rw-r--r--src/journal/test-catalog.c54
-rw-r--r--src/journal/test-compress-benchmark.c20
-rw-r--r--src/journal/test-compress.c27
-rw-r--r--src/journal/test-journal-config.c53
-rw-r--r--src/journal/test-journal-enum.c18
-rw-r--r--src/journal/test-journal-flush.c22
-rw-r--r--src/journal/test-journal-init.c18
-rw-r--r--src/journal/test-journal-interleaving.c28
-rw-r--r--src/journal/test-journal-match.c18
-rw-r--r--src/journal/test-journal-send.c18
-rw-r--r--src/journal/test-journal-stream.c30
-rw-r--r--src/journal/test-journal-syslog.c18
-rw-r--r--src/journal/test-journal-verify.c26
-rw-r--r--src/journal/test-journal.c131
-rw-r--r--src/journal/test-mmap-cache.c18
-rw-r--r--src/kernel-install/kernel-install2
-rw-r--r--src/kernel-install/meson.build15
-rw-r--r--src/libsystemd-network/arp-util.c23
-rw-r--r--src/libsystemd-network/arp-util.h17
-rw-r--r--src/libsystemd-network/dhcp-identifier.c22
-rw-r--r--src/libsystemd-network/dhcp-identifier.h18
-rw-r--r--src/libsystemd-network/dhcp-internal.h18
-rw-r--r--src/libsystemd-network/dhcp-lease-internal.h18
-rw-r--r--src/libsystemd-network/dhcp-network.c27
-rw-r--r--src/libsystemd-network/dhcp-option.c52
-rw-r--r--src/libsystemd-network/dhcp-packet.c18
-rw-r--r--src/libsystemd-network/dhcp-protocol.h17
-rw-r--r--src/libsystemd-network/dhcp-server-internal.h19
-rw-r--r--src/libsystemd-network/dhcp6-internal.h17
-rw-r--r--src/libsystemd-network/dhcp6-lease-internal.h18
-rw-r--r--src/libsystemd-network/dhcp6-network.c21
-rw-r--r--src/libsystemd-network/dhcp6-option.c22
-rw-r--r--src/libsystemd-network/dhcp6-protocol.h17
-rw-r--r--src/libsystemd-network/icmp6-util.c21
-rw-r--r--src/libsystemd-network/icmp6-util.h17
-rw-r--r--src/libsystemd-network/lldp-internal.h19
-rw-r--r--src/libsystemd-network/lldp-neighbor.c22
-rw-r--r--src/libsystemd-network/lldp-neighbor.h19
-rw-r--r--src/libsystemd-network/lldp-network.c24
-rw-r--r--src/libsystemd-network/lldp-network.h19
-rw-r--r--src/libsystemd-network/meson.build15
-rw-r--r--src/libsystemd-network/ndisc-internal.h17
-rw-r--r--src/libsystemd-network/ndisc-router.c23
-rw-r--r--src/libsystemd-network/ndisc-router.h17
-rw-r--r--src/libsystemd-network/network-internal.c140
-rw-r--r--src/libsystemd-network/network-internal.h54
-rw-r--r--src/libsystemd-network/radv-internal.h17
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c103
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c36
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c96
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c20
-rw-r--r--src/libsystemd-network/sd-dhcp6-lease.c24
-rw-r--r--src/libsystemd-network/sd-ipv4acd.c24
-rw-r--r--src/libsystemd-network/sd-ipv4ll.c21
-rw-r--r--src/libsystemd-network/sd-lldp.c30
-rw-r--r--src/libsystemd-network/sd-ndisc.c20
-rw-r--r--src/libsystemd-network/sd-radv.c49
-rw-r--r--src/libsystemd-network/test-acd.c18
-rw-r--r--src/libsystemd-network/test-dhcp-client.c19
-rw-r--r--src/libsystemd-network/test-dhcp-server.c18
-rw-r--r--src/libsystemd-network/test-dhcp6-client.c18
-rw-r--r--src/libsystemd-network/test-ipv4ll-manual.c18
-rw-r--r--src/libsystemd-network/test-ipv4ll.c17
-rw-r--r--src/libsystemd-network/test-lldp.c19
-rw-r--r--src/libsystemd-network/test-ndisc-ra.c17
-rw-r--r--src/libsystemd-network/test-ndisc-rs.c17
-rw-r--r--src/libsystemd/libsystemd.sym19
-rw-r--r--src/libsystemd/meson.build21
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.c20
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.h20
-rw-r--r--src/libsystemd/sd-bus/bus-container.c16
-rw-r--r--src/libsystemd/sd-bus/bus-container.h16
-rw-r--r--src/libsystemd/sd-bus/bus-control.c35
-rw-r--r--src/libsystemd/sd-bus/bus-control.h16
-rw-r--r--src/libsystemd/sd-bus/bus-convenience.c16
-rw-r--r--src/libsystemd/sd-bus/bus-creds.c22
-rw-r--r--src/libsystemd/sd-bus/bus-creds.h16
-rw-r--r--src/libsystemd/sd-bus/bus-dump.c16
-rw-r--r--src/libsystemd/sd-bus/bus-dump.h16
-rw-r--r--src/libsystemd/sd-bus/bus-error.c18
-rw-r--r--src/libsystemd/sd-bus/bus-error.h16
-rw-r--r--src/libsystemd/sd-bus/bus-gvariant.c16
-rw-r--r--src/libsystemd/sd-bus/bus-gvariant.h16
-rw-r--r--src/libsystemd/sd-bus/bus-internal.c16
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h29
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.c16
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.h16
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c16
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.h16
-rw-r--r--src/libsystemd/sd-bus/bus-match.c20
-rw-r--r--src/libsystemd/sd-bus/bus-match.h16
-rw-r--r--src/libsystemd/sd-bus/bus-message.c169
-rw-r--r--src/libsystemd/sd-bus/bus-message.h20
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c23
-rw-r--r--src/libsystemd/sd-bus/bus-objects.h16
-rw-r--r--src/libsystemd/sd-bus/bus-protocol.h16
-rw-r--r--src/libsystemd/sd-bus/bus-signature.c17
-rw-r--r--src/libsystemd/sd-bus/bus-signature.h16
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c77
-rw-r--r--src/libsystemd/sd-bus/bus-slot.h16
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c33
-rw-r--r--src/libsystemd/sd-bus/bus-socket.h16
-rw-r--r--src/libsystemd/sd-bus/bus-track.c46
-rw-r--r--src/libsystemd/sd-bus/bus-track.h16
-rw-r--r--src/libsystemd/sd-bus/bus-type.c16
-rw-r--r--src/libsystemd/sd-bus/bus-type.h16
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c266
-rw-r--r--src/libsystemd/sd-bus/test-bus-benchmark.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-chat.c23
-rw-r--r--src/libsystemd/sd-bus/test-bus-cleanup.c18
-rw-r--r--src/libsystemd/sd-bus/test-bus-creds.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-error.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-gvariant.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-introspect.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-marshal.c18
-rw-r--r--src/libsystemd/sd-bus/test-bus-match.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-objects.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-server.c19
-rw-r--r--src/libsystemd/sd-bus/test-bus-signature.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-track.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-watch-bind.c16
-rw-r--r--src/libsystemd/sd-daemon/sd-daemon.c19
-rw-r--r--src/libsystemd/sd-device/device-enumerator-private.h18
-rw-r--r--src/libsystemd/sd-device/device-enumerator.c22
-rw-r--r--src/libsystemd/sd-device/device-internal.h19
-rw-r--r--src/libsystemd/sd-device/device-private.c34
-rw-r--r--src/libsystemd/sd-device/device-private.h18
-rw-r--r--src/libsystemd/sd-device/device-util.h18
-rw-r--r--src/libsystemd/sd-device/sd-device.c45
-rw-r--r--src/libsystemd/sd-event/sd-event.c1007
-rw-r--r--src/libsystemd/sd-event/test-event.c166
-rw-r--r--src/libsystemd/sd-hwdb/hwdb-internal.h18
-rw-r--r--src/libsystemd/sd-hwdb/hwdb-util.h18
-rw-r--r--src/libsystemd/sd-hwdb/sd-hwdb.c22
-rw-r--r--src/libsystemd/sd-id128/id128-util.c16
-rw-r--r--src/libsystemd/sd-id128/id128-util.h16
-rw-r--r--src/libsystemd/sd-id128/sd-id128.c18
-rw-r--r--src/libsystemd/sd-login/sd-login.c94
-rw-r--r--src/libsystemd/sd-login/test-login.c16
-rw-r--r--src/libsystemd/sd-netlink/generic-netlink.c3
-rw-r--r--src/libsystemd/sd-netlink/local-addresses.c25
-rw-r--r--src/libsystemd/sd-netlink/local-addresses.h17
-rw-r--r--src/libsystemd/sd-netlink/netlink-internal.h18
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c25
-rw-r--r--src/libsystemd/sd-netlink/netlink-socket.c29
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c33
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.h20
-rw-r--r--src/libsystemd/sd-netlink/netlink-util.c22
-rw-r--r--src/libsystemd/sd-netlink/netlink-util.h20
-rw-r--r--src/libsystemd/sd-netlink/rtnl-message.c18
-rw-r--r--src/libsystemd/sd-netlink/sd-netlink.c36
-rw-r--r--src/libsystemd/sd-netlink/test-local-addresses.c16
-rw-r--r--src/libsystemd/sd-netlink/test-netlink.c23
-rw-r--r--src/libsystemd/sd-network/network-util.c16
-rw-r--r--src/libsystemd/sd-network/network-util.h18
-rw-r--r--src/libsystemd/sd-network/sd-network.c52
-rw-r--r--src/libsystemd/sd-path/sd-path.c48
-rw-r--r--src/libsystemd/sd-resolve/sd-resolve.c241
-rw-r--r--src/libsystemd/sd-resolve/test-resolve.c19
-rw-r--r--src/libsystemd/sd-utf8/sd-utf8.c16
-rw-r--r--src/libudev/libudev-device-internal.h19
-rw-r--r--src/libudev/libudev-device-private.c19
-rw-r--r--src/libudev/libudev-device.c19
-rw-r--r--src/libudev/libudev-enumerate.c25
-rw-r--r--src/libudev/libudev-hwdb.c21
-rw-r--r--src/libudev/libudev-list.c18
-rw-r--r--src/libudev/libudev-monitor.c18
-rw-r--r--src/libudev/libudev-private.h18
-rw-r--r--src/libudev/libudev-queue.c18
-rw-r--r--src/libudev/libudev-util.c18
-rw-r--r--src/libudev/libudev.c21
-rw-r--r--src/libudev/libudev.h19
-rw-r--r--src/libudev/libudev.sym2
-rw-r--r--src/libudev/meson.build15
-rw-r--r--src/locale/keymap-util.c241
-rw-r--r--src/locale/keymap-util.h33
-rw-r--r--src/locale/localectl.c221
-rw-r--r--src/locale/localed.c527
-rw-r--r--src/locale/meson.build15
-rw-r--r--src/locale/test-keymap-util.c18
-rw-r--r--src/login/inhibit.c32
-rw-r--r--src/login/loginctl.c446
-rw-r--r--src/login/logind-acl.c22
-rw-r--r--src/login/logind-acl.h19
-rw-r--r--src/login/logind-action.c64
-rw-r--r--src/login/logind-action.h24
-rw-r--r--src/login/logind-button.c39
-rw-r--r--src/login/logind-button.h19
-rw-r--r--src/login/logind-core.c100
-rw-r--r--src/login/logind-dbus.c311
-rw-r--r--src/login/logind-device.c18
-rw-r--r--src/login/logind-device.h19
-rw-r--r--src/login/logind-gperf.gperf48
-rw-r--r--src/login/logind-inhibit.c24
-rw-r--r--src/login/logind-inhibit.h20
-rw-r--r--src/login/logind-seat-dbus.c79
-rw-r--r--src/login/logind-seat.c29
-rw-r--r--src/login/logind-seat.h19
-rw-r--r--src/login/logind-session-dbus.c59
-rw-r--r--src/login/logind-session-device.c78
-rw-r--r--src/login/logind-session-device.h18
-rw-r--r--src/login/logind-session.c57
-rw-r--r--src/login/logind-session.h21
-rw-r--r--src/login/logind-user-dbus.c41
-rw-r--r--src/login/logind-user.c198
-rw-r--r--src/login/logind-user.h22
-rw-r--r--src/login/logind-utmp.c18
-rw-r--r--src/login/logind.c225
-rw-r--r--src/login/logind.conf.in1
-rw-r--r--src/login/logind.h33
-rw-r--r--src/login/meson.build29
-rw-r--r--src/login/org.freedesktop.login1.conf8
-rw-r--r--src/login/pam_systemd.c197
-rw-r--r--src/login/pam_systemd.sym2
-rw-r--r--src/login/sysfs-show.c26
-rw-r--r--src/login/sysfs-show.h19
-rw-r--r--src/login/test-inhibit.c18
-rw-r--r--src/login/test-login-shared.c18
-rw-r--r--src/login/test-login-tables.c18
-rw-r--r--src/login/user-runtime-dir.c170
-rw-r--r--src/machine-id-setup/machine-id-setup-main.c18
-rw-r--r--src/machine/image-dbus.c29
-rw-r--r--src/machine/image-dbus.h19
-rw-r--r--src/machine/machine-dbus.c75
-rw-r--r--src/machine/machine-dbus.h21
-rw-r--r--src/machine/machine.c29
-rw-r--r--src/machine/machine.h19
-rw-r--r--src/machine/machinectl.c660
-rw-r--r--src/machine/machined-dbus.c461
-rw-r--r--src/machine/machined.c106
-rw-r--r--src/machine/machined.h29
-rw-r--r--src/machine/meson.build15
-rw-r--r--src/machine/operation.c18
-rw-r--r--src/machine/operation.h19
-rw-r--r--src/machine/test-machine-tables.c20
-rw-r--r--src/modules-load/modules-load.c18
-rw-r--r--src/mount/mount-tool.c55
-rw-r--r--src/network/meson.build17
-rw-r--r--src/network/netdev/bond.c19
-rw-r--r--src/network/netdev/bond.h18
-rw-r--r--src/network/netdev/bridge.c21
-rw-r--r--src/network/netdev/bridge.h18
-rw-r--r--src/network/netdev/dummy.c20
-rw-r--r--src/network/netdev/dummy.h18
-rw-r--r--src/network/netdev/geneve.c23
-rw-r--r--src/network/netdev/geneve.h18
-rw-r--r--src/network/netdev/ipvlan.c18
-rw-r--r--src/network/netdev/ipvlan.h19
-rw-r--r--src/network/netdev/macvlan.c18
-rw-r--r--src/network/netdev/macvlan.h18
-rw-r--r--src/network/netdev/netdev-gperf.gperf6
-rw-r--r--src/network/netdev/netdev.c30
-rw-r--r--src/network/netdev/netdev.h22
-rw-r--r--src/network/netdev/netdevsim.c10
-rw-r--r--src/network/netdev/netdevsim.h14
-rw-r--r--src/network/netdev/tunnel.c22
-rw-r--r--src/network/netdev/tunnel.h18
-rw-r--r--src/network/netdev/tuntap.c20
-rw-r--r--src/network/netdev/tuntap.h18
-rw-r--r--src/network/netdev/vcan.c18
-rw-r--r--src/network/netdev/vcan.h18
-rw-r--r--src/network/netdev/veth.c18
-rw-r--r--src/network/netdev/veth.h18
-rw-r--r--src/network/netdev/vlan.c18
-rw-r--r--src/network/netdev/vlan.h18
-rw-r--r--src/network/netdev/vrf.c17
-rw-r--r--src/network/netdev/vrf.h17
-rw-r--r--src/network/netdev/vxcan.c19
-rw-r--r--src/network/netdev/vxcan.h19
-rw-r--r--src/network/netdev/vxlan.c18
-rw-r--r--src/network/netdev/vxlan.h18
-rw-r--r--src/network/netdev/wireguard.c35
-rw-r--r--src/network/netdev/wireguard.h17
-rw-r--r--src/network/networkctl.c46
-rw-r--r--src/network/networkd-address-label.c42
-rw-r--r--src/network/networkd-address-label.h24
-rw-r--r--src/network/networkd-address-pool.c18
-rw-r--r--src/network/networkd-address-pool.h19
-rw-r--r--src/network/networkd-address.c55
-rw-r--r--src/network/networkd-address.h34
-rw-r--r--src/network/networkd-brvlan.c17
-rw-r--r--src/network/networkd-brvlan.h25
-rw-r--r--src/network/networkd-conf.c17
-rw-r--r--src/network/networkd-conf.h43
-rw-r--r--src/network/networkd-dhcp4.c62
-rw-r--r--src/network/networkd-dhcp6.c23
-rw-r--r--src/network/networkd-fdb.c29
-rw-r--r--src/network/networkd-fdb.h23
-rw-r--r--src/network/networkd-ipv4ll.c30
-rw-r--r--src/network/networkd-ipv6-proxy-ndp.c17
-rw-r--r--src/network/networkd-ipv6-proxy-ndp.h21
-rw-r--r--src/network/networkd-link-bus.c21
-rw-r--r--src/network/networkd-link.c437
-rw-r--r--src/network/networkd-link.h21
-rw-r--r--src/network/networkd-lldp-tx.c23
-rw-r--r--src/network/networkd-lldp-tx.h19
-rw-r--r--src/network/networkd-manager-bus.c18
-rw-r--r--src/network/networkd-manager.c38
-rw-r--r--src/network/networkd-manager.h20
-rw-r--r--src/network/networkd-ndisc.c27
-rw-r--r--src/network/networkd-ndisc.h18
-rw-r--r--src/network/networkd-network-bus.c39
-rw-r--r--src/network/networkd-network-gperf.gperf25
-rw-r--r--src/network/networkd-network.c98
-rw-r--r--src/network/networkd-network.h101
-rw-r--r--src/network/networkd-radv.c44
-rw-r--r--src/network/networkd-radv.h32
-rw-r--r--src/network/networkd-route.c376
-rw-r--r--src/network/networkd-route.h46
-rw-r--r--src/network/networkd-routing-policy-rule.c51
-rw-r--r--src/network/networkd-routing-policy-rule.h32
-rw-r--r--src/network/networkd-util.c39
-rw-r--r--src/network/networkd-util.h25
-rw-r--r--src/network/networkd.c28
-rw-r--r--src/network/test-network-tables.c30
-rw-r--r--src/network/test-network.c26
-rw-r--r--src/network/test-networkd-conf.c78
-rw-r--r--src/network/test-routing-policy-rule.c17
-rw-r--r--src/network/wait-online/link.c19
-rw-r--r--src/network/wait-online/link.h19
-rw-r--r--src/network/wait-online/manager.c21
-rw-r--r--src/network/wait-online/manager.h18
-rw-r--r--src/network/wait-online/wait-online.c18
-rw-r--r--src/notify/notify.c18
-rw-r--r--src/nspawn/meson.build42
-rw-r--r--src/nspawn/nspawn-cgroup.c77
-rw-r--r--src/nspawn/nspawn-cgroup.h21
-rw-r--r--src/nspawn/nspawn-def.h19
-rw-r--r--src/nspawn/nspawn-expose-ports.c21
-rw-r--r--src/nspawn/nspawn-expose-ports.h19
-rw-r--r--src/nspawn/nspawn-gperf.gperf87
-rw-r--r--src/nspawn/nspawn-mount.c183
-rw-r--r--src/nspawn/nspawn-mount.h38
-rw-r--r--src/nspawn/nspawn-network.c30
-rw-r--r--src/nspawn/nspawn-network.h19
-rw-r--r--src/nspawn/nspawn-patch-uid.c21
-rw-r--r--src/nspawn/nspawn-patch-uid.h18
-rw-r--r--src/nspawn/nspawn-register.c32
-rw-r--r--src/nspawn/nspawn-register.h19
-rw-r--r--src/nspawn/nspawn-seccomp.c18
-rw-r--r--src/nspawn/nspawn-seccomp.h19
-rw-r--r--src/nspawn/nspawn-settings.c231
-rw-r--r--src/nspawn/nspawn-settings.h163
-rw-r--r--src/nspawn/nspawn-setuid.c28
-rw-r--r--src/nspawn/nspawn-setuid.h19
-rw-r--r--src/nspawn/nspawn-stub-pid1.c18
-rw-r--r--src/nspawn/nspawn-stub-pid1.h19
-rw-r--r--src/nspawn/nspawn.c1106
-rw-r--r--src/nspawn/test-nspawn-tables.c11
-rw-r--r--src/nspawn/test-patch-uid.c18
-rw-r--r--src/nss-myhostname/nss-myhostname.c18
-rw-r--r--src/nss-myhostname/nss-myhostname.sym2
-rw-r--r--src/nss-mymachines/nss-mymachines.c28
-rw-r--r--src/nss-mymachines/nss-mymachines.sym2
-rw-r--r--src/nss-resolve/nss-resolve.c18
-rw-r--r--src/nss-resolve/nss-resolve.sym2
-rw-r--r--src/nss-systemd/nss-systemd.c486
-rw-r--r--src/nss-systemd/nss-systemd.sym8
-rw-r--r--src/partition/growfs.c18
-rw-r--r--src/partition/makefs.c17
-rw-r--r--src/path/path.c20
-rw-r--r--src/portable/meson.build29
-rw-r--r--src/portable/org.freedesktop.portable1.conf117
-rw-r--r--src/portable/org.freedesktop.portable1.policy43
-rw-r--r--src/portable/org.freedesktop.portable1.service7
-rw-r--r--src/portable/portable.c1427
-rw-r--r--src/portable/portable.h77
-rw-r--r--src/portable/portablectl.c968
-rw-r--r--src/portable/portabled-bus.c402
-rw-r--r--src/portable/portabled-bus.h10
-rw-r--r--src/portable/portabled-image-bus.c731
-rw-r--r--src/portable/portabled-image-bus.h40
-rw-r--r--src/portable/portabled-image.c105
-rw-r--r--src/portable/portabled-image.h11
-rw-r--r--src/portable/portabled-operation.c128
-rw-r--r--src/portable/portabled-operation.h29
-rw-r--r--src/portable/portabled.c168
-rw-r--r--src/portable/portabled.h25
-rw-r--r--src/portable/profile/default/service.conf32
-rw-r--r--src/portable/profile/nonetwork/service.conf32
-rw-r--r--src/portable/profile/strict/service.conf31
-rw-r--r--src/portable/profile/trusted/service.conf7
-rw-r--r--src/quotacheck/quotacheck.c18
-rw-r--r--src/random-seed/random-seed.c18
-rw-r--r--src/rc-local-generator/rc-local-generator.c19
-rw-r--r--src/remount-fs/remount-fs.c18
-rw-r--r--src/reply-password/reply-password.c18
-rw-r--r--src/resolve/dns-type.c18
-rw-r--r--src/resolve/dns-type.h19
-rw-r--r--src/resolve/meson.build27
-rw-r--r--src/resolve/resolv.conf2
-rw-r--r--src/resolve/resolvconf-compat.c283
-rw-r--r--src/resolve/resolvconf-compat.h3
-rw-r--r--src/resolve/resolvectl.c (renamed from src/resolve/resolve-tool.c)1852
-rw-r--r--src/resolve/resolvectl.h30
-rw-r--r--src/resolve/resolved-bus.c118
-rw-r--r--src/resolve/resolved-bus.h22
-rw-r--r--src/resolve/resolved-conf.c35
-rw-r--r--src/resolve/resolved-conf.h31
-rw-r--r--src/resolve/resolved-def.h22
-rw-r--r--src/resolve/resolved-dns-answer.c46
-rw-r--r--src/resolve/resolved-dns-answer.h37
-rw-r--r--src/resolve/resolved-dns-cache.c27
-rw-r--r--src/resolve/resolved-dns-cache.h19
-rw-r--r--src/resolve/resolved-dns-dnssec.c79
-rw-r--r--src/resolve/resolved-dns-dnssec.h20
-rw-r--r--src/resolve/resolved-dns-packet.c62
-rw-r--r--src/resolve/resolved-dns-packet.h18
-rw-r--r--src/resolve/resolved-dns-query.c30
-rw-r--r--src/resolve/resolved-dns-query.h20
-rw-r--r--src/resolve/resolved-dns-question.c46
-rw-r--r--src/resolve/resolved-dns-question.h27
-rw-r--r--src/resolve/resolved-dns-rr.c27
-rw-r--r--src/resolve/resolved-dns-rr.h17
-rw-r--r--src/resolve/resolved-dns-scope.c74
-rw-r--r--src/resolve/resolved-dns-scope.h22
-rw-r--r--src/resolve/resolved-dns-search-domain.c21
-rw-r--r--src/resolve/resolved-dns-search-domain.h19
-rw-r--r--src/resolve/resolved-dns-server.c143
-rw-r--r--src/resolve/resolved-dns-server.h39
-rw-r--r--src/resolve/resolved-dns-stream.c287
-rw-r--r--src/resolve/resolved-dns-stream.h48
-rw-r--r--src/resolve/resolved-dns-stub.c28
-rw-r--r--src/resolve/resolved-dns-stub.h22
-rw-r--r--src/resolve/resolved-dns-synthesize.c24
-rw-r--r--src/resolve/resolved-dns-synthesize.h19
-rw-r--r--src/resolve/resolved-dns-transaction.c267
-rw-r--r--src/resolve/resolved-dns-transaction.h20
-rw-r--r--src/resolve/resolved-dns-trust-anchor.c66
-rw-r--r--src/resolve/resolved-dns-trust-anchor.h19
-rw-r--r--src/resolve/resolved-dns-zone.c30
-rw-r--r--src/resolve/resolved-dns-zone.h19
-rw-r--r--src/resolve/resolved-dnssd-bus.c21
-rw-r--r--src/resolve/resolved-dnssd-bus.h18
-rw-r--r--src/resolve/resolved-dnssd.c29
-rw-r--r--src/resolve/resolved-dnssd.h18
-rw-r--r--src/resolve/resolved-etc-hosts.c18
-rw-r--r--src/resolve/resolved-etc-hosts.h19
-rw-r--r--src/resolve/resolved-gperf.gperf1
-rw-r--r--src/resolve/resolved-link-bus.c106
-rw-r--r--src/resolve/resolved-link-bus.h20
-rw-r--r--src/resolve/resolved-link.c86
-rw-r--r--src/resolve/resolved-link.h23
-rw-r--r--src/resolve/resolved-llmnr.c20
-rw-r--r--src/resolve/resolved-llmnr.h19
-rw-r--r--src/resolve/resolved-manager.c49
-rw-r--r--src/resolve/resolved-manager.h22
-rw-r--r--src/resolve/resolved-mdns.c30
-rw-r--r--src/resolve/resolved-mdns.h18
-rw-r--r--src/resolve/resolved-resolv-conf.c22
-rw-r--r--src/resolve/resolved-resolv-conf.h18
-rw-r--r--src/resolve/resolved.c20
-rw-r--r--src/resolve/resolved.conf.in1
-rw-r--r--src/resolve/test-dns-packet.c18
-rw-r--r--src/resolve/test-dnssec-complex.c23
-rw-r--r--src/resolve/test-dnssec.c18
-rw-r--r--src/resolve/test-resolve-tables.c18
-rw-r--r--src/resolve/test-resolved-packet.c18
-rw-r--r--src/rfkill/rfkill.c48
-rw-r--r--src/run/run.c32
-rw-r--r--src/shared/acl-util.c33
-rw-r--r--src/shared/acl-util.h19
-rw-r--r--src/shared/acpi-fpdt.c18
-rw-r--r--src/shared/acpi-fpdt.h18
-rw-r--r--src/shared/apparmor-util.c18
-rw-r--r--src/shared/apparmor-util.h19
-rw-r--r--src/shared/ask-password-api.c21
-rw-r--r--src/shared/ask-password-api.h33
-rw-r--r--src/shared/base-filesystem.c20
-rw-r--r--src/shared/base-filesystem.h18
-rw-r--r--src/shared/boot-timestamps.c19
-rw-r--r--src/shared/boot-timestamps.h19
-rw-r--r--src/shared/bootspec.c35
-rw-r--r--src/shared/bootspec.h22
-rw-r--r--src/shared/bus-unit-util.c151
-rw-r--r--src/shared/bus-unit-util.h23
-rw-r--r--src/shared/bus-util.c445
-rw-r--r--src/shared/bus-util.h91
-rw-r--r--src/shared/cgroup-show.c29
-rw-r--r--src/shared/cgroup-show.h19
-rw-r--r--src/shared/clean-ipc.c18
-rw-r--r--src/shared/clean-ipc.h19
-rw-r--r--src/shared/condition.c27
-rw-r--r--src/shared/condition.h19
-rw-r--r--src/shared/conf-parser.c275
-rw-r--r--src/shared/conf-parser.h225
-rw-r--r--src/shared/dev-setup.c18
-rw-r--r--src/shared/dev-setup.h19
-rw-r--r--src/shared/dissect-image.c225
-rw-r--r--src/shared/dissect-image.h21
-rw-r--r--src/shared/dns-domain.c69
-rw-r--r--src/shared/dns-domain.h18
-rw-r--r--src/shared/dropin.c103
-rw-r--r--src/shared/dropin.h20
-rw-r--r--src/shared/efivars.c40
-rw-r--r--src/shared/efivars.h19
-rw-r--r--src/shared/fdset.c33
-rw-r--r--src/shared/fdset.h21
-rw-r--r--src/shared/firewall-util.c19
-rw-r--r--src/shared/firewall-util.h19
-rw-r--r--src/shared/fstab-util.c27
-rw-r--r--src/shared/fstab-util.h19
-rw-r--r--src/shared/generator.c18
-rw-r--r--src/shared/generator.h19
-rw-r--r--src/shared/gpt.h20
-rw-r--r--src/shared/ima-util.c18
-rw-r--r--src/shared/ima-util.h19
-rw-r--r--src/shared/import-util.c22
-rw-r--r--src/shared/import-util.h19
-rw-r--r--src/shared/initreq.h1
-rw-r--r--src/shared/install-printf.c46
-rw-r--r--src/shared/install-printf.h19
-rw-r--r--src/shared/install.c416
-rw-r--r--src/shared/install.h63
-rw-r--r--src/shared/journal-util.c19
-rw-r--r--src/shared/journal-util.h19
-rw-r--r--src/shared/libshared.sym2
-rw-r--r--src/shared/linux/auto_dev-ioctl.h4
-rw-r--r--src/shared/linux/libbpf.h1
-rw-r--r--src/shared/logs-show.c141
-rw-r--r--src/shared/logs-show.h30
-rw-r--r--src/shared/loop-util.c25
-rw-r--r--src/shared/loop-util.h19
-rw-r--r--src/shared/machine-image.c397
-rw-r--r--src/shared/machine-image.h41
-rw-r--r--src/shared/machine-pool.c32
-rw-r--r--src/shared/machine-pool.h19
-rw-r--r--src/shared/meson.build29
-rw-r--r--src/shared/nsflags.c70
-rw-r--r--src/shared/nsflags.h32
-rw-r--r--src/shared/output-mode.c21
-rw-r--r--src/shared/output-mode.h20
-rw-r--r--src/shared/pager.h31
-rw-r--r--src/shared/path-lookup.c124
-rw-r--r--src/shared/path-lookup.h21
-rw-r--r--src/shared/ptyfwd.c21
-rw-r--r--src/shared/ptyfwd.h19
-rw-r--r--src/shared/resolve-util.c25
-rw-r--r--src/shared/resolve-util.h41
-rw-r--r--src/shared/seccomp-util.c102
-rw-r--r--src/shared/seccomp-util.h28
-rw-r--r--src/shared/sleep-config.c210
-rw-r--r--src/shared/sleep-config.h24
-rw-r--r--src/shared/spawn-ask-password-agent.c18
-rw-r--r--src/shared/spawn-ask-password-agent.h19
-rw-r--r--src/shared/spawn-polkit-agent.c18
-rw-r--r--src/shared/spawn-polkit-agent.h27
-rw-r--r--src/shared/specifier.c56
-rw-r--r--src/shared/specifier.h22
-rw-r--r--src/shared/switch-root.c17
-rw-r--r--src/shared/switch-root.h20
-rw-r--r--src/shared/sysctl-util.c18
-rw-r--r--src/shared/sysctl-util.h19
-rw-r--r--src/shared/test-tables.h18
-rw-r--r--src/shared/tests.c18
-rw-r--r--src/shared/tests.h19
-rw-r--r--src/shared/tomoyo-util.c18
-rw-r--r--src/shared/tomoyo-util.h18
-rw-r--r--src/shared/udev-util.c43
-rw-r--r--src/shared/udev-util.h32
-rw-r--r--src/shared/uid-range.c19
-rw-r--r--src/shared/uid-range.h19
-rw-r--r--src/shared/utmp-wtmp.c19
-rw-r--r--src/shared/utmp-wtmp.h19
-rw-r--r--src/shared/vlan-util.c18
-rw-r--r--src/shared/vlan-util.h25
-rw-r--r--src/shared/volatile-util.c45
-rw-r--r--src/shared/volatile-util.h20
-rw-r--r--src/shared/watchdog.c20
-rw-r--r--src/shared/watchdog.h19
-rw-r--r--src/sleep/sleep.c198
-rw-r--r--src/socket-proxy/socket-proxyd.c17
-rw-r--r--src/stdio-bridge/stdio-bridge.c18
-rw-r--r--src/sulogin-shell/sulogin-shell.c17
-rw-r--r--src/sysctl/sysctl.c64
-rw-r--r--src/system-update-generator/system-update-generator.c22
-rw-r--r--src/systemctl/systemctl.c1341
-rw-r--r--src/systemd/_sd-common.h3
-rw-r--r--src/systemd/meson.build32
-rw-r--r--src/systemd/sd-bus-protocol.h3
-rw-r--r--src/systemd/sd-bus-vtable.h3
-rw-r--r--src/systemd/sd-bus.h14
-rw-r--r--src/systemd/sd-daemon.h3
-rw-r--r--src/systemd/sd-device.h5
-rw-r--r--src/systemd/sd-dhcp-client.h13
-rw-r--r--src/systemd/sd-dhcp-lease.h6
-rw-r--r--src/systemd/sd-dhcp-server.h6
-rw-r--r--src/systemd/sd-dhcp6-client.h4
-rw-r--r--src/systemd/sd-dhcp6-lease.h5
-rw-r--r--src/systemd/sd-event.h10
-rw-r--r--src/systemd/sd-hwdb.h5
-rw-r--r--src/systemd/sd-id128.h3
-rw-r--r--src/systemd/sd-ipv4acd.h6
-rw-r--r--src/systemd/sd-ipv4ll.h4
-rw-r--r--src/systemd/sd-journal.h3
-rw-r--r--src/systemd/sd-lldp.h5
-rw-r--r--src/systemd/sd-login.h3
-rw-r--r--src/systemd/sd-messages.h3
-rw-r--r--src/systemd/sd-ndisc.h4
-rw-r--r--src/systemd/sd-netlink.h4
-rw-r--r--src/systemd/sd-network.h13
-rw-r--r--src/systemd/sd-path.h4
-rw-r--r--src/systemd/sd-radv.h12
-rw-r--r--src/systemd/sd-resolve.h9
-rw-r--r--src/systemd/sd-utf8.h3
-rw-r--r--src/sysusers/sysusers.c364
-rw-r--r--src/sysv-generator/sysv-generator.c32
-rw-r--r--src/test/meson.build45
-rw-r--r--src/test/test-acl-util.c18
-rw-r--r--src/test/test-af-list.c18
-rw-r--r--src/test/test-alloc-util.c39
-rw-r--r--src/test/test-architecture.c18
-rw-r--r--src/test/test-arphrd-list.c18
-rw-r--r--src/test/test-ask-password-api.c18
-rw-r--r--src/test/test-async.c18
-rw-r--r--src/test/test-barrier.c18
-rw-r--r--src/test/test-bitmap.c18
-rw-r--r--src/test/test-boot-timestamps.c19
-rw-r--r--src/test/test-bpf.c26
-rw-r--r--src/test/test-btrfs.c18
-rw-r--r--src/test/test-bus-util.c90
-rw-r--r--src/test/test-calendarspec.c19
-rw-r--r--src/test/test-cap-list.c18
-rw-r--r--src/test/test-capability.c18
-rw-r--r--src/test/test-cgroup-mask.c42
-rw-r--r--src/test/test-cgroup-util.c36
-rw-r--r--src/test/test-cgroup.c18
-rw-r--r--src/test/test-clock.c17
-rw-r--r--src/test/test-condition.c53
-rw-r--r--src/test/test-conf-files.c45
-rw-r--r--src/test/test-conf-parser.c24
-rw-r--r--src/test/test-copy.c57
-rw-r--r--src/test/test-cpu-set-util.c18
-rw-r--r--src/test/test-daemon.c18
-rw-r--r--src/test/test-date.c18
-rw-r--r--src/test/test-device-nodes.c17
-rw-r--r--src/test/test-dissect-image.c18
-rw-r--r--src/test/test-dlopen.c20
-rw-r--r--src/test/test-dns-domain.c17
-rw-r--r--src/test/test-ellipsize.c135
-rw-r--r--src/test/test-engine.c51
-rw-r--r--src/test/test-env-util.c28
-rw-r--r--src/test/test-escape.c18
-rw-r--r--src/test/test-exec-util.c20
-rw-r--r--src/test/test-execute.c52
-rw-r--r--src/test/test-extract-word.c19
-rw-r--r--src/test/test-fd-util.c118
-rw-r--r--src/test/test-fdset.c18
-rw-r--r--src/test/test-fileio.c87
-rw-r--r--src/test/test-firewall-util.c18
-rw-r--r--src/test/test-format-table.c139
-rw-r--r--src/test/test-fs-util.c69
-rw-r--r--src/test/test-fstab-util.c18
-rw-r--r--src/test/test-gcrypt-util.c4
-rw-r--r--src/test/test-glob-util.c18
-rw-r--r--src/test/test-hash.c18
-rw-r--r--src/test/test-hashmap-plain.c17
-rw-r--r--src/test/test-hashmap.c19
-rw-r--r--src/test/test-helper.c18
-rw-r--r--src/test/test-helper.h17
-rw-r--r--src/test/test-hexdecoct.c201
-rw-r--r--src/test/test-hostname-util.c20
-rw-r--r--src/test/test-hostname.c18
-rw-r--r--src/test/test-id128.c18
-rw-r--r--src/test/test-in-addr-util.c18
-rw-r--r--src/test/test-install-root.c40
-rw-r--r--src/test/test-install.c20
-rw-r--r--src/test/test-io-util.c18
-rw-r--r--src/test/test-ipcrm.c18
-rw-r--r--src/test/test-job-type.c19
-rw-r--r--src/test/test-journal-importer.c18
-rw-r--r--src/test/test-libudev.c31
-rw-r--r--src/test/test-list.c17
-rw-r--r--src/test/test-locale-util.c45
-rw-r--r--src/test/test-log.c27
-rw-r--r--src/test/test-loopback.c18
-rw-r--r--src/test/test-mount-util.c18
-rw-r--r--src/test/test-namespace.c18
-rw-r--r--src/test/test-netlink-manual.c18
-rw-r--r--src/test/test-ns.c18
-rw-r--r--src/test/test-nss.c22
-rw-r--r--src/test/test-os-util.c22
-rw-r--r--src/test/test-parse-util.c93
-rw-r--r--src/test/test-path-lookup.c24
-rw-r--r--src/test/test-path-util.c79
-rw-r--r--src/test/test-path.c40
-rw-r--r--src/test/test-prioq.c18
-rw-r--r--src/test/test-proc-cmdline.c18
-rw-r--r--src/test/test-process-util.c82
-rw-r--r--src/test/test-procfs-util.c2
-rw-r--r--src/test/test-random-util.c18
-rw-r--r--src/test/test-ratelimit.c30
-rw-r--r--src/test/test-replace-var.c18
-rw-r--r--src/test/test-rlimit-util.c52
-rw-r--r--src/test/test-sched-prio.c43
-rw-r--r--src/test/test-seccomp.c66
-rw-r--r--src/test/test-selinux.c18
-rw-r--r--src/test/test-set.c63
-rw-r--r--src/test/test-sigbus.c18
-rw-r--r--src/test/test-signal-util.c118
-rw-r--r--src/test/test-siphash24.c18
-rw-r--r--src/test/test-sizeof.c40
-rw-r--r--src/test/test-sleep.c83
-rw-r--r--src/test/test-socket-util.c31
-rw-r--r--src/test/test-specifier.c18
-rw-r--r--src/test/test-stat-util.c26
-rw-r--r--src/test/test-strbuf.c32
-rw-r--r--src/test/test-string-util.c116
-rw-r--r--src/test/test-strip-tab-ansi.c41
-rw-r--r--src/test/test-strv.c20
-rw-r--r--src/test/test-strxcpyx.c18
-rwxr-xr-xsrc/test/test-systemd-tmpfiles.py6
-rw-r--r--src/test/test-tables.c44
-rw-r--r--src/test/test-terminal-util.c45
-rw-r--r--src/test/test-time-util.c79
-rw-r--r--src/test/test-tmpfiles.c18
-rw-r--r--src/test/test-udev.c26
-rw-r--r--src/test/test-uid-range.c18
-rw-r--r--src/test/test-umount.c57
-rw-r--r--src/test/test-unaligned.c18
-rw-r--r--src/test/test-unit-file.c97
-rw-r--r--src/test/test-unit-name.c498
-rw-r--r--src/test/test-user-util.c18
-rw-r--r--src/test/test-utf8.c40
-rw-r--r--src/test/test-util.c23
-rw-r--r--src/test/test-verbs.c18
-rw-r--r--src/test/test-watch-pid.c5
-rw-r--r--src/test/test-watchdog.c18
-rw-r--r--src/test/test-web-util.c22
-rw-r--r--src/test/test-xattr-util.c18
-rw-r--r--src/test/test-xml.c18
-rw-r--r--src/time-wait-sync/time-wait-sync.c265
-rw-r--r--src/timedate/meson.build15
-rw-r--r--src/timedate/org.freedesktop.timedate1.policy6
-rw-r--r--src/timedate/timedatectl.c729
-rw-r--r--src/timedate/timedated.c470
-rw-r--r--src/timesync/meson.build26
-rw-r--r--src/timesync/org.freedesktop.timesync1.conf42
-rw-r--r--src/timesync/org.freedesktop.timesync1.service14
-rw-r--r--src/timesync/test-timesync.c24
-rw-r--r--src/timesync/timesyncd-bus.c197
-rw-r--r--src/timesync/timesyncd-bus.h6
-rw-r--r--src/timesync/timesyncd-conf.c27
-rw-r--r--src/timesync/timesyncd-conf.h20
-rw-r--r--src/timesync/timesyncd-manager.c135
-rw-r--r--src/timesync/timesyncd-manager.h28
-rw-r--r--src/timesync/timesyncd-ntp-message.h45
-rw-r--r--src/timesync/timesyncd-server.c18
-rw-r--r--src/timesync/timesyncd-server.h18
-rw-r--r--src/timesync/timesyncd.c60
-rw-r--r--src/tmpfiles/tmpfiles.c192
-rw-r--r--src/tty-ask-password-agent/tty-ask-password-agent.c18
-rw-r--r--src/udev/ata_id/ata_id.c23
-rw-r--r--src/udev/cdrom_id/cdrom_id.c13
-rw-r--r--src/udev/collect/collect.c2
-rw-r--r--src/udev/meson.build36
-rw-r--r--src/udev/mtd_probe/mtd_probe.c32
-rw-r--r--src/udev/mtd_probe/mtd_probe.h4
-rw-r--r--src/udev/mtd_probe/probe_smartmedia.c44
-rw-r--r--src/udev/net/ethtool-util.c124
-rw-r--r--src/udev/net/ethtool-util.h33
-rw-r--r--src/udev/net/link-config-gperf.gperf14
-rw-r--r--src/udev/net/link-config.c33
-rw-r--r--src/udev/net/link-config.h24
-rw-r--r--src/udev/scsi_id/scsi_id.c31
-rw-r--r--src/udev/scsi_id/scsi_id.h14
-rw-r--r--src/udev/scsi_id/scsi_serial.c19
-rw-r--r--src/udev/udev-builtin-blkid.c17
-rw-r--r--src/udev/udev-builtin-btrfs.c18
-rw-r--r--src/udev/udev-builtin-hwdb.c24
-rw-r--r--src/udev/udev-builtin-input_id.c22
-rw-r--r--src/udev/udev-builtin-keyboard.c18
-rw-r--r--src/udev/udev-builtin-kmod.c15
-rw-r--r--src/udev/udev-builtin-net_id.c172
-rw-r--r--src/udev/udev-builtin-net_setup_link.c18
-rw-r--r--src/udev/udev-builtin-path_id.c42
-rw-r--r--src/udev/udev-builtin-uaccess.c14
-rw-r--r--src/udev/udev-builtin-usb_id.c15
-rw-r--r--src/udev/udev-builtin.c18
-rw-r--r--src/udev/udev-ctrl.c1
-rw-r--r--src/udev/udev-event.c13
-rw-r--r--src/udev/udev-node.c17
-rw-r--r--src/udev/udev-rules.c13
-rw-r--r--src/udev/udev-watch.c17
-rw-r--r--src/udev/udev.h15
-rw-r--r--src/udev/udevadm-control.c10
-rw-r--r--src/udev/udevadm-hwdb.c52
-rw-r--r--src/udev/udevadm-info.c19
-rw-r--r--src/udev/udevadm-monitor.c21
-rw-r--r--src/udev/udevadm-settle.c17
-rw-r--r--src/udev/udevadm-test-builtin.c13
-rw-r--r--src/udev/udevadm-test.c21
-rw-r--r--src/udev/udevadm-trigger.c25
-rw-r--r--src/udev/udevadm-util.c13
-rw-r--r--src/udev/udevadm-util.h14
-rw-r--r--src/udev/udevadm.c13
-rw-r--r--src/udev/udevd.c66
-rw-r--r--src/udev/v4l_id/v4l_id.c1
-rw-r--r--src/update-done/update-done.c18
-rw-r--r--src/update-utmp/update-utmp.c18
-rw-r--r--src/user-sessions/user-sessions.c18
-rw-r--r--src/vconsole/meson.build15
-rw-r--r--src/vconsole/vconsole-setup.c90
-rw-r--r--src/veritysetup/veritysetup-generator.c18
-rw-r--r--src/veritysetup/veritysetup.c18
-rw-r--r--src/volatile-root/volatile-root.c18
-rw-r--r--sysctl.d/50-default.conf3
-rw-r--r--sysctl.d/meson.build15
-rw-r--r--sysusers.d/meson.build17
-rw-r--r--sysusers.d/systemd.conf.m46
-rwxr-xr-xtest/TEST-03-JOBS/test-jobs.sh2
-rwxr-xr-xtest/TEST-03-JOBS/test.sh3
-rwxr-xr-xtest/TEST-06-SELINUX/test.sh3
-rwxr-xr-xtest/TEST-15-DROPIN/test.sh2
-rwxr-xr-xtest/TEST-16-EXTEND-TIMEOUT/test.sh1
-rw-r--r--test/TEST-21-SYSUSERS/test-11.expected-group6
-rw-r--r--test/TEST-21-SYSUSERS/test-11.expected-passwd6
-rw-r--r--test/TEST-21-SYSUSERS/test-11.initial-group4
-rw-r--r--test/TEST-21-SYSUSERS/test-11.initial-passwd5
-rw-r--r--test/TEST-21-SYSUSERS/test-11.input3
-rw-r--r--test/TEST-21-SYSUSERS/test-12.expected-group2
-rw-r--r--test/TEST-21-SYSUSERS/test-12.expected-passwd2
-rw-r--r--test/TEST-21-SYSUSERS/test-12.initial-group1
-rw-r--r--test/TEST-21-SYSUSERS/test-12.initial-passwd1
-rw-r--r--test/TEST-21-SYSUSERS/test-12.input1
-rwxr-xr-xtest/TEST-21-SYSUSERS/test.sh19
-rwxr-xr-xtest/TEST-22-TMPFILES/test.sh2
-rwxr-xr-xtest/create-sys-script.py16
-rw-r--r--test/fuzz-corpus/.gitattributes1
-rw-r--r--test/fuzz-corpus/journal-remote/invalid-ts.txtbin0 -> 4657 bytes
-rw-r--r--test/fuzz-corpus/journal-remote/sample.txt180
-rw-r--r--test/fuzz-corpus/unit-file/dev-mapper-fedora_krowka\x2dswap.swap10
-rw-r--r--test/fuzz-corpus/unit-file/directives.service910
-rw-r--r--test/fuzz-corpus/unit-file/empty.scope2
-rw-r--r--test/fuzz-corpus/unit-file/machine.slice14
-rw-r--r--test/fuzz-corpus/unit-file/proc-sys-fs-binfmt_misc.automount21
-rw-r--r--test/fuzz-corpus/unit-file/syslog.socket117
-rw-r--r--test/fuzz-corpus/unit-file/systemd-ask-password-console.path22
-rw-r--r--test/fuzz-corpus/unit-file/systemd-machined.service34
-rw-r--r--test/fuzz-corpus/unit-file/systemd-resolved.service50
-rw-r--r--test/fuzz-corpus/unit-file/systemd-tmpfiles-clean.timer40
-rw-r--r--test/fuzz-corpus/unit-file/timers.target16
-rw-r--r--test/fuzz-corpus/unit-file/var-lib-machines.mount19
-rw-r--r--test/fuzz-regressions/.gitattributes1
-rw-r--r--test/fuzz-regressions/fuzz-dns-packet/issue-7888 (renamed from test/fuzz-regressions/address/fuzz-dns-packet/issue-7888)bin25 -> 25 bytes
-rw-r--r--test/fuzz-regressions/fuzz-dns-packet/oss-fuzz-5465 (renamed from test/fuzz-regressions/address/fuzz-dns-packet/oss-fuzz-5465)bin24 -> 24 bytes
-rw-r--r--test/fuzz-regressions/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76bin0 -> 7675 bytes
-rw-r--r--test/fuzz-regressions/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45bin0 -> 2490 bytes
-rw-r--r--test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-86598
-rw-r--r--test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-86866
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-68843
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-68853
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-68863
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-68923
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-68974
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897-evverx4
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-69083
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-69174
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-69773
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977-unminimized3
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-70043
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-80643
-rw-r--r--test/fuzz-regressions/fuzz-unit-file/oss-fuzz-88275
-rw-r--r--test/fuzz-regressions/meson.build38
-rwxr-xr-xtest/hwdb-test.sh13
-rw-r--r--test/meson.build40
-rwxr-xr-xtest/networkd-test.py38
-rwxr-xr-xtest/rule-syntax-check.py15
-rwxr-xr-xtest/run-integration-tests.sh12
-rwxr-xr-xtest/sys-script.py16
-rwxr-xr-xtest/sysv-generator-test.py15
-rwxr-xr-xtest/test-exec-deserialization.py15
-rw-r--r--test/test-execute/exec-basic.service13
-rw-r--r--test/test-execute/exec-bindpaths.service8
-rw-r--r--test/test-execute/exec-capabilityboundingset-invert.service2
-rw-r--r--test/test-execute/exec-dynamicuser-statedir-migrate-step1.service16
-rw-r--r--test/test-execute/exec-dynamicuser-statedir-migrate-step2.service34
-rw-r--r--test/test-execute/exec-dynamicuser-statedir.service18
-rw-r--r--test/test-execute/exec-environmentfile.service2
-rw-r--r--test/test-execute/exec-passenvironment-absent.service4
-rw-r--r--test/test-execute/exec-passenvironment-empty.service4
-rw-r--r--test/test-execute/exec-passenvironment-repeated.service4
-rw-r--r--test/test-execute/exec-passenvironment.service4
-rw-r--r--test/test-execute/exec-personality-aarch64.service2
-rw-r--r--test/test-execute/exec-privatedevices-disabled-by-prefix.service8
-rw-r--r--test/test-execute/exec-privatedevices-no.service2
-rw-r--r--test/test-execute/exec-privatedevices-yes.service2
-rw-r--r--test/test-execute/exec-privatenetwork-yes.service2
-rw-r--r--test/test-execute/exec-restrictnamespaces-merge-all.service8
-rw-r--r--test/test-execute/exec-restrictnamespaces-merge-and.service9
-rw-r--r--test/test-execute/exec-restrictnamespaces-merge-or.service9
-rw-r--r--test/test-execute/exec-restrictnamespaces-mnt-blacklist.service2
-rw-r--r--test/test-execute/exec-restrictnamespaces-mnt.service2
-rw-r--r--test/test-execute/exec-restrictnamespaces-no.service2
-rw-r--r--test/test-execute/exec-restrictnamespaces-yes.service2
-rw-r--r--test/test-execute/exec-runtimedirectory.service2
-rw-r--r--test/test-execute/exec-specifier-interpolation.service2
-rw-r--r--test/test-execute/exec-specifier.service43
-rw-r--r--test/test-execute/exec-specifier@.service41
-rw-r--r--test/test-execute/exec-temporaryfilesystem-rw.service16
-rw-r--r--test/test-execute/exec-workingdirectory-trailing-dot.service7
-rw-r--r--test/test-functions21
-rw-r--r--test/test-umount/empty.mountinfo0
-rw-r--r--test/test-umount/example.swaps4
-rw-r--r--test/test-umount/garbled.mountinfo5
-rw-r--r--test/test-umount/rhbug-1554943.mountinfo47
-rwxr-xr-xtest/udev-test.pl3
-rw-r--r--test/unit-.service.d/10-override.conf2
-rw-r--r--test/unit-with-.service.d/20-override.conf2
-rw-r--r--test/unit-with-multiple-.service.d/20-override.conf2
-rw-r--r--test/unit-with-multiple-.service.d/30-override.conf2
-rw-r--r--test/unit-with-multiple-dashes.service6
-rw-r--r--test/unit-with-multiple-dashes.service.d/10-override.conf2
-rw-r--r--tmpfiles.d/meson.build20
-rw-r--r--tmpfiles.d/portables.conf4
-rw-r--r--tmpfiles.d/systemd.conf.m410
-rwxr-xr-xtools/catalog-report.py5
-rwxr-xr-xtools/coverity.sh (renamed from scripts/coverity.sh)11
-rwxr-xr-xtools/find-double-newline.sh42
-rwxr-xr-xtools/find-tabs.sh42
-rw-r--r--tools/gdb-sd_dump_hashmaps.py17
-rwxr-xr-xtools/make-directive-index.py26
-rwxr-xr-xtools/make-man-index.py27
-rwxr-xr-xtools/make-man-rules.py17
-rwxr-xr-xtools/meson-apply-m4.sh24
-rwxr-xr-xtools/meson-build.sh10
-rwxr-xr-xtools/meson-hwdb-update.sh4
-rwxr-xr-xtools/oss-fuzz.sh (renamed from scripts/oss-fuzz.sh)30
-rwxr-xr-xtools/xml_helper.py17
-rw-r--r--travis-ci/Dockerfile3
-rw-r--r--travis-ci/requirements.txt1
-rwxr-xr-xtravis-ci/scripts/build-docker-image.sh5
-rwxr-xr-xtravis-ci/tools/get-docker-remote.sh20
-rw-r--r--units/console-getty.service.m4 (renamed from units/console-getty.service.m4.in)0
-rw-r--r--units/container-getty@.service.m4 (renamed from units/container-getty@.service.m4.in)0
-rw-r--r--units/meson.build47
-rw-r--r--units/suspend-then-hibernate.target16
-rw-r--r--units/system-update-cleanup.service (renamed from units/system-update-cleanup.service.in)0
-rw-r--r--units/system-update-pre.target15
-rw-r--r--units/system-update.target2
-rw-r--r--units/systemd-coredump@.service.in3
-rw-r--r--units/systemd-hostnamed.service.in3
-rw-r--r--units/systemd-importd.service.in3
-rw-r--r--units/systemd-journald.service.in3
-rw-r--r--units/systemd-localed.service.in3
-rw-r--r--units/systemd-logind.service.in5
-rw-r--r--units/systemd-machined.service.in3
-rw-r--r--units/systemd-networkd.service.in8
-rw-r--r--units/systemd-portabled.service.in26
-rw-r--r--units/systemd-resolved.service.in9
-rw-r--r--units/systemd-suspend-then-hibernate.service.in19
-rw-r--r--units/systemd-time-wait-sync.service.in36
-rw-r--r--units/systemd-timedated.service.in3
-rw-r--r--units/systemd-timesyncd.service.in7
-rw-r--r--units/systemd-udev-trigger.service.in3
-rw-r--r--units/systemd-udevd.service.in4
-rw-r--r--units/user-.slice.d/10-defaults.conf15
-rw-r--r--units/user-runtime-dir@.service.in17
-rw-r--r--units/user/meson.build15
-rw-r--r--units/user/systemd-exit.service.in2
-rw-r--r--units/user@.service.in2
1895 files changed, 54288 insertions, 52195 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
deleted file mode 100644
index 687270eaae..0000000000
--- a/.github/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,31 +0,0 @@
-### Submission type
-
-<!-- Delete the inappropriate option below: -->
-
- - Bug report
- - Request for enhancement (RFE)
-
-<!-- **NOTE:** Do not submit anything other than bug reports or RFEs via the issue tracker! -->
-
-### systemd version the issue has been seen with
-
-> …
-
-<!-- **NOTE:** Do not submit bug reports about anything but the two most recently released systemd versions upstream! -->
-<!-- For older version please use distribution trackers (see https://github.com/systemd/systemd/blob/master/.github/CONTRIBUTING.md#filing-issues). -->
-
-### Used distribution
-
-> …
-
-### In case of bug report: Expected behaviour you didn't see
-
-> …
-
-### In case of bug report: Unexpected behaviour you saw
-
-> …
-
-### In case of bug report: Steps to reproduce the problem
-
-> …
diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md
new file mode 100644
index 0000000000..cea1c655b9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Bug_report.md
@@ -0,0 +1,22 @@
+---
+name: Bug report
+about: A report of an error in a recent systemd version
+
+---
+
+**systemd version the issue has been seen with**
+> ...
+
+<!-- **NOTE:** Do not submit bug reports about anything but the two most recently released systemd versions upstream! -->
+<!-- For older version please use distribution trackers (see https://github.com/systemd/systemd/blob/master/.github/CONTRIBUTING.md#filing-issues). -->
+
+**Used distribution**
+ > …
+
+**Expected behaviour you didn't see**
+ > …
+
+**Unexpected behaviour you saw**
+ > …
+
+**Steps to reproduce the problem**
diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md
new file mode 100644
index 0000000000..c56aae8730
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Feature_request.md
@@ -0,0 +1,14 @@
+---
+name: Feature request
+about: Suggest an improvement
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
diff --git a/.mailmap b/.mailmap
index 5c825d43a8..83b17bfb2b 100644
--- a/.mailmap
+++ b/.mailmap
@@ -151,3 +151,13 @@ Robert Kolchmeyer <rkolchmeyer@google.com> <rkolchmeyer@users.noreply.github.com
George Gaydarov <git@gg7.io> <gg7@users.noreply.github.com>
Bill Yodlowsky <bill@redhat.com> <itsbill@users.noreply.github.com>
Mao Huang <littlecvr@gmail.com>
+Pavel Hrdina <phrdina@redhat.com>
+Jürg Billeter <j@bitron.ch>
+Leonard König <leonard.r.koenig@googlemail.com>
+Milan Pässler <me@petabyteboy.de>
+Wim van Mourik <wvanmourik@computest.nl> <githubw@use.startmail.com>
+Rubén Suárez Alvarez <rubensa@tluportatil082> <rubensa@gmail.com>
+Salvo Tomaselli <ltworf@users.noreply.github.com>
+Matthew McGinn <mamcgi@gmail.com> <xginn8@users.noreply.github.com>
+Evgeny Vereshchagin <evvers@ya.ru>
+Peter D'Hoye <peter.dhoye@gmail.com>
diff --git a/.mkosi/mkosi.arch b/.mkosi/mkosi.arch
index dac80d38f7..05620cd1e9 100644
--- a/.mkosi/mkosi.arch
+++ b/.mkosi/mkosi.arch
@@ -1,21 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2016 Zeal Jagannatha
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2016 Zeal Jagannatha
# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi).
# Simply invoke "mkosi" in the project directory to build an OS image.
diff --git a/.mkosi/mkosi.debian b/.mkosi/mkosi.debian
index de47df1847..d30a592bc4 100644
--- a/.mkosi/mkosi.debian
+++ b/.mkosi/mkosi.debian
@@ -1,21 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2016 Daniel Rusek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2016 Daniel Rusek
# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi).
# Simply invoke "mkosi" in the project directory to build an OS image.
diff --git a/.mkosi/mkosi.fedora b/.mkosi/mkosi.fedora
index 0aeb7751cb..63027d9fc7 100644
--- a/.mkosi/mkosi.fedora
+++ b/.mkosi/mkosi.fedora
@@ -1,21 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# This file is part of systemd.
-#
-# Copyright 2016 Lennart Poettering
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi).
# Simply invoke "mkosi" in the project directory to build an OS image.
@@ -47,6 +30,7 @@ BuildPackages=
gnu-efi-devel
gnutls-devel
gperf
+ hostname
iptables-devel
kmod-devel
libacl-devel
diff --git a/.mkosi/mkosi.ubuntu b/.mkosi/mkosi.ubuntu
new file mode 100644
index 0000000000..bbda5dd054
--- /dev/null
+++ b/.mkosi/mkosi.ubuntu
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# Copyright 2016 Daniel Rusek
+
+# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi).
+# Simply invoke "mkosi" in the project directory to build an OS image.
+
+[Distribution]
+Distribution=ubuntu
+Release=bionic
+Repositories=main,universe
+
+[Output]
+Format=raw_btrfs
+Bootable=no
+
+[Partitions]
+RootSize=2G
+
+[Packages]
+BuildPackages=
+ acl
+ docbook-xml
+ docbook-xsl
+ gcc
+ gettext
+ git
+ gnu-efi
+ gperf
+ iptables-dev
+ libacl1-dev
+ libaudit-dev
+ libblkid-dev
+ libbz2-dev
+ libcap-dev
+ libcryptsetup-dev
+ libcurl4-gnutls-dev
+ libdbus-1-dev
+ libdw-dev
+ libfdisk-dev
+ libgcrypt20-dev
+ libgnutls28-dev
+ libidn2-0-dev
+ libkmod-dev
+ liblz4-dev
+ liblz4-tool
+ liblzma-dev
+ libmicrohttpd-dev
+ libmount-dev
+ libpam0g-dev
+ libqrencode-dev
+ libseccomp-dev
+ libsmartcols-dev
+ libtool
+ libxkbcommon-dev
+ m4
+ meson
+ pkg-config
+ python3
+ python3-lxml
+ tree
+ tzdata
+ uuid-dev
+ xsltproc
+ xz-utils
+
+Packages=
+ libqrencode3
+ locales
+ libidn2-0
diff --git a/.travis.yml b/.travis.yml
index 1f09a78fa6..d980038181 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,72 +3,23 @@ sudo: required
services:
- docker
+language: c
+
jobs:
include:
- - stage: build docker image
- env:
- # The machine id will be passed to Dockerfile for later checks
- - MACHINE_ID=$(cat /var/lib/dbus/machine-id)
- before_script: &update
- # Ensure the latest version of docker is installed
+ - stage: coverity scan
+ before_script:
- sudo apt-get update
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- docker --version
- env > .env
- script:
- # Copy content of CI_DIR into WORKDIR
- - find $CI_DIR -maxdepth 1 -type f -exec cp -t . {} +
- - echo "ENV GIT_SHA ${TRAVIS_COMMIT}" >> Dockerfile
- - echo "ENV MACHINE_ID ${MACHINE_ID}" >> Dockerfile
- - echo "$(git log -1 ${TRAVIS_COMMIT})" >> COMMITINFO
- # Build docker container
- - $CI_SCRIPT_DIR/build-docker-image.sh
-
- - docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}"
- - docker push ${DOCKER_REPOSITORY}
-
- - stage: build
- language: c
- compiler: gcc
- env:
- # The machine id will be passed to container
- - MACHINE_ID=$(cat /var/lib/dbus/machine-id)
- before_script: *update
- script:
- - docker run -dit --name travis_build ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} bash
- - docker exec -u 0 -ti travis_build bash -c "echo ${MACHINE_ID} > /etc/machine-id"
- - docker exec -ti travis_build meson build
- - docker exec -ti travis_build ninja -C build
- # Commit it to the new image that will be used for testing
- - docker commit -m "systemd build state" -a "${AUTHOR_NAME}" travis_build ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT}
- - docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}"
- - docker push ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT}
-
- - stage: test
- language: c
- compiler: gcc
- before_script: *update
- script:
- - docker run --privileged --net=host -dit --name travis_test ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} bash
- - docker exec -ti travis_test ninja -C build test
- - docker commit -m "systemd test state" -a "${AUTHOR_NAME}" travis_test ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT}
- - docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}"
- - docker push ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT}
-
- - stage: coverity scan
- language: c
- compiler: gcc
- before_script: *update
env:
- COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG"
- COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
- COVERITY_SCAN_BRANCH_PATTERN="$TRAVIS_BRANCH"
- # Disable CCACHE for cov-build to compilation units correctly
- - CCACHE_DISABLE=1
- # Token for systemd/systemd Coverity Scan Analysis
- # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
- # via the "travis encrypt" command using the project repo's public key
- - secure: "UNQLspT89GYWuVKFqW5W5RyqqnYg5RvX20IrNraOddhpdV9nhKBtozrfmhGXDGZwfHGWHt6g7YROlD/NIMvDvThVJIEYvSQiXCoo2zRrwkl2siET5MjPfRG8numiLq0KX47KGmyBJISJZCgDUdNGqqGwgf7AhDN78I3XtgqjFT1z0mGl8n0wiFpKPi7i3nECvF4Mk7xCCHqwByaq0z5G9NkVlOvP1EyCxwv3B6I5Umfch7ibp7iH44YnVXILK+yEry5dMuctYwYkDouR80ChEPQQ5fhhpO4++HJmFuSpfMTeCHpucAd2xwSUijejYeN/GNQ177GxSSk/8hRBGcuSK8T/WJ+KiuJPhZObV8mw+a6+qdQssWY4F9jya5ZKbZ/yTbxjtQ0m4AgtL28P9bEze8pLh16zFMX+hIEuoFSNmJqmtNttfbD5TKyYVZml59s9wvhlvMnlNpRSQva88OAOjXtiA41g+XtTxxpfW9mgd7HYhzSBs1efNiK7PfkANgve7KIYMAmCAqasgb1IIAyX7stOlJH06QOFXNH55PmJLkkKyL3SMQzgryMDWegU+XbS8t43r0x14WLuE7sc9JtnOr/G8hthFaMRp8xLy9aCBwyEIkEsyWa50VMoZDa3Spdb4r1CKBwcGdCbyE4rCehwEIznbfrsSovhwiUds7bbhBU="
+ # Encrypted token for systemd/systemd Coverity Scan Analysis,
+ # generated by "travis encrypt -r systemd/systemd COVERITY_SCAN_TOKEN=<TOKEN>"
+ - secure: "lM0IVP2zOG5Ywk3YCbDCQL4WioyzzwtdtpZ+hKDy4BWCZDBJ/FVwIeBsXdMDvlTa3xi+GQ1b7kS2OmTfmG4aSlhU7isuH8SMq1Y4GR5AxfhkR+irUA1A1fntlvhbjIumDGW5wjs0Dt8KogMWS+ZD4eGE59lrVO/TrhMzIe1eHENVLFQJdNq+ZJXU8wxMfHf8lXk0xA8SJTid0XvZBNc4JN6pjJRA8LaOrMNhQYfygFmVQ598kwlu7gf5vbCKFPnIgJAxdIhz12XS9utGohV28IYj9d1DdUGUT+ar3OfADj3X8KFBP4Ymc02pcln3wVgdPtrDbFZh1R9jbmfdXGAH/6tTOJVn8aFySS2Vq9QiBiprWdPsAOLcWMNhnp0lMkASxs9/W26nU7Czo8VbAVWXM1w35plDpnDGR6lk/06dmOZpqu5p3AYr5xIKACIAdPDn0rNpnSWqC750WZ8ZWbHnKuZC5TWML7scVaPiEi7D7rbwqML2rdwx4ZoTZmCHiGByXCIWTfhf0JNQAix5WW3znl+BmDesumPgPj2mX+y6J1WYJrIz12m7qh7KhV/a1ODKM+I91A9rkOA/bPnmhmSSUR7CwgvZt1fC/VwBnaFFtAz9/70kN9Q8tDBXtXidExZwh1e3t5vDG72k3lXwNqpKRvdW3LOxK6lFvqEdMWVUJls="
script:
# Copy content of CI_DIR into WORKDIR
- find $CI_DIR -maxdepth 1 -type f -exec cp -t . {} +
@@ -94,71 +45,23 @@ jobs:
- |
docker run -dit --env-file .cov-env \
-v ${TOOL_BASE}:${TOOL_BASE}:ro \
- --name travis_coverity_scan ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} bash
+ --name travis_coverity_scan coverity-${TRAVIS_COMMIT}:latest bash
# Make sure Coverity script is executable
- - docker cp scripts/coverity.sh travis_coverity_scan:/usr/local/bin
+ - docker cp tools/coverity.sh travis_coverity_scan:/usr/local/bin
# Preconfigure with meson to prevent Coverity from capturing meson metadata
# Set compiler flag to prevent emit failure
- - docker exec -it travis_coverity_scan sh -c "CFLAGS='-D_Float128=long\ double' meson cov-build -Dman=false"
+ - docker exec -it travis_coverity_scan sh -c "CFLAGS='-D_Float128=long\ double -D_Float64=double -D_Float64x=long\ double -D_Float32=float -D_Float32x=double' meson cov-build -Dman=false"
# Run Coverity Analysis
- docker exec -it travis_coverity_scan coverity.sh build
- docker exec -it travis_coverity_scan coverity.sh upload
- - stage: clean docker
- language: python
- # python:
- # - "3.6" Probably broken ATM
- env:
- - SIZE_LIMIT="3000" # Limit in MBs
- - TAG_LIMIT="3" # Number of tags to be kept at the time
- before-script:
- - sudo apt-get -y install python3
- script:
- # Get docker-remote tool and setup venv
- - sudo $CI_TOOL_DIR/get-docker-remote.sh
- # Activate virtual environment to be able to use docker-remote safely
- - source venv/bin/activate
- # Check the size and tag limit of the repo
- - REPO_SIZE=$(docker-remote repository --size $DOCKER_REPOSITORY)
- - TAG_COUNT=$(docker-remote tags --count $DOCKER_REPOSITORY)
- - 'echo -e "\033[33;1mCurrent repository size: $REPO_SIZE in $TAG_COUNT tags \033[0m"'
- - |
- if [[ ${REPO_SIZE%.*} -gt $SIZE_LIMIT ]] || [[ $TAG_COUNT -gt $TAG_LIMIT ]]
- then
- docker-remote --login $DOCKER_USERNAME:$DOCKER_PASSWORD \
- tags --assumeyes --pop-back --keep $TAG_LIMIT $DOCKER_REPOSITORY
- fi
-
-
-
# Specify the order of stages and conditions
stages:
- # Helper stage to determine whether coverity stage should be allowed
- - name: initialization
-
- - name: build docker image
- if: type != cron
- - name: build
- if: type != cron
- - name: test
- if: type != cron
-
- # These stages run separately, the resulting container will not be pushed to Docker Hub
- # This stage will only run on special conditions
- name: coverity scan
if: type = cron
- # Check for repository size and clean Docker repo if necessary
- - name: clean Docker
- if: type = cron
-
env:
global:
- # Secure Docker Hub credentials
- - secure: "TY61ufmEJyxCer8vuAlQ3mYwGRynFZXPCFTxKgIzobAHHyE1Zwx0bZDDwDd88Gdgz7EGnOJtMABfa0axfPOK9il5u7lYmmZ8Usa0HAvKavkpSRnw2b16zz88N98x3DyaIquvg2J8iQpHHoM32+BGiAS7P8BiYTO6r+E0CMPYC0Ylh7eHVSBGfWbR9m+yCo/mDIEAWyop6Jv4rTMN4qP9U7e6Kou7m/AJeiCWMaR7rlanpLFNQi3+qF/Mt5dbE7LVLNSOkmpg/FPw34g4RC5mfLAh+c8YBadqo6kFA6qV1b931or0aZUYVtobI6UwC9U1GGqzfCTjXuVMNgPBBQ6n3JMt91mFFkP0lXdGMxpBNbwFL/btBrt2a359L/wNtqv6PuSJwJ3oTe/FP++X6xjbM7LcAHZMWZiK+0BFefNOUcRzBpaEJ2nGNzcLKHn4Bl0pl4LwZ0uVocN8RBwHnDX+hyUwwQPoQTLJQB9tpwDweIzftt9KmrIHmL9v7KZXR4s/8CKpNfVQ/XSysdtsK+7EKK5AsnbMNrZLjpH7D0Lo/Xp92/eJ2UGyqI7awJbJGPV2FNwyGcojDEXIBUsVssUjb5+B4LpHP1x4UQe/m9SuPJdtRB0R7PKe/tyPD3GTyfVO9K7imQATDdnMY32nkWXmXej8YWo76yA732rTZRZtFAc="
- - secure: "NAEzWn5Ru6IqDA1RSyTVhpIp2iQluumg0EOI111EN7qWWGUDNgAZi+QgvRI+OBNyuMpBpN/GX1Ys4YxUDos1F/fhm2vytoB4A/LG463FQsSVP3wnyMFJTSOI8H0jgK41xj79qiww7edbfq93MZ/XS95Ws4tUTi/0etUGvAgIHGgofFCPPdMNkOvSHLgzSnYfydzLuD9FVpCgvpbJnQ+47XHyN+sKoA+OlZ+EfIOVZt+Mk/dqYrsM7MRKEfplk1MvUiJpHvrw+xWTslCIiO03V6ws091fBMgedIFRpsySrsd1KwH8JIeOK6KFn5W7Q53auzZkKYk7ymknlJt4WVBy7Qg33njMQ53t3qMQYTRUIV4dcR60cdII7tatzgpKBcycxHQMAshOYPT6pYhSsO6JEKgiO+ZhOxvqWGwtEeH9Zq7P4ft8Q7GJhRkdi0X0WY7/6RjwinO/1LLj1LODim3mDFfAK7xS7e+nQW/JEOdWohT2+qm97j9IOZeQtPtdqZP9F8HJXgw6WjiGJIXMF3Ov9GkQh4uJyMYJ6hN7T3iRoenV86Dzgg6u5Ku131Ziwvlm+n94qlXF8Jl47wCcAS7VmyYxMft1gH+Zs+4Wq7KO0vysmnEk6rCqb87ZQSDOdTzBfK9HTyyAqmBCgS4Dp5x7/xOBMVXfq/SOb9c3Sh/JItA="
- - DOCKER_REPOSITORY=$DOCKER_USERNAME/systemd
-
- ADMIN_EMAIL=macermak@redhat.com
- AUTHOR_NAME="$(git log -1 $TRAVIS_COMMIT --pretty=\"%aN\")"
@@ -172,9 +75,3 @@ notifications:
email:
recipients:
- ${ADMIN_EMAIL}
- - ${AUTHOR_EMAIL}
- irc:
- channels:
- - "irc.freenode.org#systemd"
- on_success: change
- on_failure: always
diff --git a/NEWS b/NEWS
index 52724587ed..fb00f4ba63 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,381 @@
systemd System and Service Manager
+CHANGES WITH 239:
+
+ * NETWORK INTERFACE DEVICE NAMING CHANGES: systemd-udevd's "net_id"
+ builtin will name network interfaces differently than in previous
+ versions for virtual network interfaces created with SR-IOV and NPAR
+ and for devices where the PCI network controller device does not have
+ a slot number associated.
+
+ SR-IOV virtual devices are now named based on the name of the parent
+ interface, with a suffix of "v<N>", where <N> is the virtual device
+ number. Previously those virtual devices were named as if completely
+ independent.
+
+ The ninth and later NPAR virtual devices will be named following the
+ scheme used for the first eight NPAR partitions. Previously those
+ devices were not renamed and the kernel default (eth<n>) was used.
+
+ "net_id" will also generate names for PCI devices where the PCI
+ network controller device does not have an associated slot number
+ itself, but one of its parents does. Previously those devices were
+ not renamed and the kernel default (eth<n>) was used.
+
+ * AF_INET and AF_INET6 are dropped from RestrictAddressFamilies= in
+ systemd-logind.service. Since v235, IPAddressDeny=any has been set to
+ the unit. So, it is expected that the default behavior of
+ systemd-logind is not changed. However, if distribution packagers or
+ administrators disabled or modified IPAddressDeny= setting by a
+ drop-in config file, then it may be necessary to update the file to
+ re-enable AF_INET and AF_INET6 to support network user name services,
+ e.g. NIS.
+
+ * When the RestrictNamespaces= unit property is specified multiple
+ times, then the specified types are merged now. Previously, only the
+ last assignment was used. So, if distribution packagers or
+ administrators modified the setting by a drop-in config file, then it
+ may be necessary to update the file.
+
+ * When OnFailure= is used in combination with Restart= on a service
+ unit, then the specified units will no longer be triggered on
+ failures that result in restarting. Previously, the specified units
+ would be activated each time the unit failed, even when the unit was
+ going to be restarted automatically. This behaviour contradicted the
+ documentation. With this release the code is adjusted to match the
+ documentation.
+
+ * systemd-tmpfiles will now print a notice whenever it encounters
+ tmpfiles.d/ lines referencing the /var/run/ directory. It will
+ recommend reworking them to use the /run/ directory instead (for
+ which /var/run/ is simply a symlinked compatibility alias). This way
+ systemd-tmpfiles can properly detect line conflicts and merge lines
+ referencing the same file by two paths, without having to access
+ them.
+
+ * systemctl disable/unmask/preset/preset-all cannot be used with
+ --runtime. Previously this was allowed, but resulted in unintuitive
+ behaviour that wasn't useful. systemctl disable/unmask will now undo
+ both runtime and persistent enablement/masking, i.e. it will remove
+ any relevant symlinks both in /run and /etc.
+
+ * Note that all long-running system services shipped with systemd will
+ now default to a system call whitelist (rather than a blacklist, as
+ before). In particular, systemd-udevd will now enforce one too. For
+ most cases this should be safe, however downstream distributions
+ which disabled sandboxing of systemd-udevd (specifically the
+ MountFlags= setting), might want to disable this security feature
+ too, as the default whitelisting will prohibit all mount, swap,
+ reboot and clock changing operations from udev rules.
+
+ * sd-boot acquired new loader configuration settings to optionally turn
+ off Windows and MacOS boot partition discovery as well as
+ reboot-into-firmware menu items. It is also able to pick a better
+ screen resolution for HiDPI systems, and now provides loader
+ configuration settings to change the resolution explicitly.
+
+ * systemd-resolved now supports DNS-over-TLS. It's still
+ turned off by default, use DNSOverTLS=opportunistic to turn it on in
+ resolved.conf. We intend to make this the default as soon as couple
+ of additional techniques for optimizing the initial latency caused by
+ establishing a TLS/TCP connection are implemented.
+
+ * systemd-resolved.service and systemd-networkd.service now set
+ DynamicUser=yes. The users systemd-resolve and systemd-network are
+ not created by systemd-sysusers.
+
+ * The systemd-resolve tool has been renamed to resolvectl (it also
+ remains available under the old name, for compatibility), and its
+ interface is now verb-based, similar in style to the other <xyz>ctl
+ tools, such as systemctl or loginctl.
+
+ * The resolvectl/systemd-resolve tool also provides 'resolvconf'
+ compatibility. It may be symlinked under the 'resolvconf' name, in
+ which case it will take arguments and input compatible with the
+ Debian and FreeBSD resolvconf tool.
+
+ * Support for suspend-then-hibernate has been added, i.e. a sleep mode
+ where the system initially suspends, and after a time-out resumes and
+ hibernates again.
+
+ * networkd's ClientIdentifier= now accepts a new option "duid-only". If
+ set the client will only send a DUID as client identifier.
+
+ * The nss-systemd glibc NSS module will now enumerate dynamic users and
+ groups in effect. Previously, it could resolve UIDs/GIDs to user
+ names/groups and vice versa, but did not support enumeration.
+
+ * journald's Compress= configuration setting now optionally accepts a
+ byte threshold value. All journal objects larger than this threshold
+ will be compressed, smaller ones will not. Previously this threshold
+ was not configurable and set to 512.
+
+ * A new system.conf setting NoNewPrivileges= is now available which may
+ be used to turn off acquisition of new privileges system-wide
+ (i.e. set Linux' PR_SET_NO_NEW_PRIVS for PID 1 itself, and thus also
+ for all its children). Note that turning this option on means setuid
+ binaries and file system capabilities lose their special powers.
+ While turning on this option is a big step towards a more secure
+ system, doing so is likely to break numerous pre-existing UNIX tools,
+ in particular su and sudo.
+
+ * A new service systemd-time-sync-wait.service has been added. If
+ enabled it will delay the time-sync.target unit at boot until time
+ synchronization has been received from the network. This
+ functionality is useful on systems lacking a local RTC or where it is
+ acceptable that the boot process shall be delayed by external network
+ services.
+
+ * When hibernating, systemd will now inform the kernel of the image
+ write offset, on kernels new enough to support this. This means swap
+ files should work for hibernation now.
+
+ * When loading unit files, systemd will now look for drop-in unit files
+ extensions in additional places. Previously, for a unit file name
+ "foo-bar-baz.service" it would look for dropin files in
+ "foo-bar-baz.service.d/*.conf". Now, it will also look in
+ "foo-bar-.service.d/*.conf" and "foo-.service.d/", i.e. at the
+ service name truncated after all inner dashes. This scheme allows
+ writing drop-ins easily that apply to a whole set of unit files at
+ once. It's particularly useful for mount and slice units (as their
+ naming is prefix based), but is also useful for service and other
+ units, for packages that install multiple unit files at once,
+ following a strict naming regime of beginning the unit file name with
+ the package's name. Two new specifiers are now supported in unit
+ files to match this: %j and %J are replaced by the part of the unit
+ name following the last dash.
+
+ * Unit files and other configuration files that support specifier
+ expansion now understand another three new specifiers: %T and %V will
+ resolve to /tmp and /var/tmp respectively, or whatever temporary
+ directory has been set for the calling user. %E will expand to either
+ /etc (for system units) or $XDG_CONFIG_HOME (for user units).
+
+ * The ExecStart= lines of unit files are no longer required to
+ reference absolute paths. If non-absolute paths are specified the
+ specified binary name is searched within the service manager's
+ built-in $PATH, which may be queried with 'systemd-path
+ search-binaries-default'. It's generally recommended to continue to
+ use absolute paths for all binaries specified in unit files.
+
+ * Units gained a new load state "bad-setting", which is used when a
+ unit file was loaded, but contained fatal errors which prevent it
+ from being started (for example, a service unit has been defined
+ lacking both ExecStart= and ExecStop= lines).
+
+ * coredumpctl's "gdb" verb has been renamed to "debug", in order to
+ support alternative debuggers, for example lldb. The old name
+ continues to be available however, for compatibility reasons. Use the
+ new --debugger= switch or the $SYSTEMD_DEBUGGER environment variable
+ to pick an alternative debugger instead of the default gdb.
+
+ * systemctl and the other tools will now output escape sequences that
+ generate proper clickable hyperlinks in various terminal emulators
+ where useful (for example, in the "systemctl status" output you can
+ now click on the unit file name to quickly open it in the
+ editor/viewer of your choice). Note that not all terminal emulators
+ support this functionality yet, but many do. Unfortunately, the
+ "less" pager doesn't support this yet, hence this functionality is
+ currently automatically turned off when a pager is started (which
+ happens quite often due to auto-paging). We hope to remove this
+ limitation as soon as "less" learns these escape sequences. This new
+ behaviour may also be turned off explicitly with the $SYSTEMD_URLIFY
+ environment variable. For details on these escape sequences see:
+ https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
+
+ * networkd's .network files now support a new IPv6MTUBytes= option for
+ setting the MTU used by IPv6 explicitly as well as a new MTUBytes=
+ option in the [Route] section to configure the MTU to use for
+ specific routes. It also gained support for configuration of the DHCP
+ "UserClass" option through the new UserClass= setting. It gained
+ three new options in the new [CAN] section for configuring CAN
+ networks. The MULTICAST and ALLMULTI interface flags may now be
+ controlled explicitly with the new Multicast= and AllMulticast=
+ settings.
+
+ * networkd will now automatically make use of the kernel's route
+ expiration feature, if it is available.
+
+ * udevd's .link files now support setting the number of receive and
+ transmit channels, using the RxChannels=, TxChannels=,
+ OtherChannels=, CombinedChannels= settings.
+
+ * Support for UDPSegmentationOffload= has been removed, given its
+ limited support in hardware, and waning software support.
+
+ * networkd's .netdev files now support creating "netdevsim" interfaces.
+
+ * PID 1 learnt a new bus call GetUnitByControlGroup() which may be used
+ to query the unit belonging to a specific kernel control group.
+
+ * systemd-analyze gained a new verb "cat-config", which may be used to
+ dump the contents of any configuration file, with all its matching
+ drop-in files added in, and honouring the usual search and masking
+ logic applied to systemd configuration files. For example use
+ "systemd-analyze cat-config systemd/system.conf" to get the complete
+ system configuration file of systemd how it would be loaded by PID 1
+ itself. Similar to this, various tools such as systemd-tmpfiles or
+ systemd-sysusers, gained a new option "--cat-config", which does the
+ corresponding operation for their own configuration settings. For
+ example, "systemd-tmpfiles --cat-config" will now output the full
+ list of tmpfiles.d/ lines in place.
+
+ * timedatectl gained three new verbs: "show" shows bus properties of
+ systemd-timedated, "timesync-status" shows the current NTP
+ synchronization state of systemd-timesyncd, and "show-timesync"
+ shows bus properties of systemd-timesyncd.
+
+ * systemd-timesyncd gained a bus interface on which it exposes details
+ about its state.
+
+ * A new environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES is now
+ understood by systemd-timedated. It takes a colon-separated list of
+ unit names of NTP client services. The list is used by
+ "timedatectl set-ntp".
+
+ * systemd-nspawn gained a new --rlimit= switch for setting initial
+ resource limits for the container payload. There's a new switch
+ --hostname= to explicitly override the container's hostname. A new
+ --no-new-privileges= switch may be used to control the
+ PR_SET_NO_NEW_PRIVS flag for the container payload. A new
+ --oom-score-adjust= switch controls the OOM scoring adjustment value
+ for the payload. The new --cpu-affinity= switch controls the CPU
+ affinity of the container payload. The new --resolv-conf= switch
+ allows more detailed control of /etc/resolv.conf handling of the
+ container. Similarly, the new --timezone= switch allows more detailed
+ control of /etc/localtime handling of the container.
+
+ * systemd-detect-virt gained a new --list switch, which will print a
+ list of all currently known VM and container environments.
+
+ * Support for "Portable Services" has been added, see
+ doc/PORTABLE_SERVICES.md for details. Currently, the support is still
+ experimental, but this is expected to change soon. Reflecting this
+ experimental state, the "portablectl" binary is not installed into
+ /usr/bin yet. The binary has to be called with the full path
+ /usr/lib/systemd/portablectl instead.
+
+ * journalctl's and systemctl's -o switch now knows a new log output
+ mode "with-unit". The output it generates is very similar to the
+ regular "short" mode, but displays the unit name instead of the
+ syslog tag for each log line. Also, the date is shown with timezone
+ information. This mode is probably more useful than the classic
+ "short" output mode for most purposes, except where pixel-perfect
+ compatibility with classic /var/log/messages formatting is required.
+
+ * A new --dump-bus-properties switch has been added to the systemd
+ binary, which may be used to dump all supported D-Bus properties.
+ (Options which are still supported, but are deprecated, are *not*
+ shown.)
+
+ * sd-bus gained a set of new calls:
+ sd_bus_slot_set_floating()/sd_bus_slot_get_floating() may be used to
+ enable/disable the "floating" state of a bus slot object,
+ i.e. whether the slot object pins the bus it is allocated for into
+ memory or if the bus slot object gets disconnected when the bus goes
+ away. sd_bus_open_with_description(),
+ sd_bus_open_user_with_description(),
+ sd_bus_open_system_with_description() may be used to allocate bus
+ objects and set their description string already during allocation.
+
+ * sd-event gained support for watching inotify events from the event
+ loop, in an efficient way, sharing inotify handles between multiple
+ users. For this a new function sd_event_add_inotify() has been added.
+
+ * sd-event and sd-bus gained support for calling special user-supplied
+ destructor functions for userdata pointers associated with
+ sd_event_source, sd_bus_slot, and sd_bus_track objects. For this new
+ functions sd_bus_slot_set_destroy_callback,
+ sd_bus_slot_get_destroy_callback, sd_bus_track_set_destroy_callback,
+ sd_bus_track_get_destroy_callback,
+ sd_event_source_set_destroy_callback,
+ sd_event_source_get_destroy_callback have been added.
+
+ * The "net.ipv4.tcp_ecn" sysctl will now be turned on by default.
+
+ * PID 1 will now automatically reschedule .timer units whenever the
+ local timezone changes. (They previously got rescheduled
+ automatically when the system clock changed.)
+
+ * New documentation has been added to document cgroups delegation,
+ portable services and the various code quality tools we have set up:
+
+ https://github.com/systemd/systemd/blob/master/doc/CGROUP_DELEGATION.md
+ https://github.com/systemd/systemd/blob/master/doc/PORTABLE_SERVICES.md
+ https://github.com/systemd/systemd/blob/master/doc/CODE_QUALITY.md
+
+ * The Boot Loader Specification has been added to the source tree.
+
+ https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md
+
+ While moving it into our source tree we have updated it and further
+ changes are now accepted through the usual github PR workflow.
+
+ * pam_systemd will now look for PAM userdata fields systemd.memory_max,
+ systemd.tasks_max, systemd.cpu_weight, systemd.io_weight set by
+ earlier PAM modules. The data in these fields is used to initialize
+ the session scope's resource properties. Thus external PAM modules
+ may now configure per-session limits, for example sourced from
+ external user databases.
+
+ * socket units with Accept=yes will now maintain a "refused" counter in
+ addition to the existing "accepted" counter, counting connections
+ refused due to the enforced limits.
+
+ * The "systemd-path search-binaries-default" command may now be use to
+ query the default, built-in $PATH PID 1 will pass to the services it
+ manages.
+
+ * A new unit file setting PrivateMounts= has been added. It's a boolean
+ option. If enabled the unit's processes are invoked in their own file
+ system namespace. Note that this behaviour is also implied if any
+ other file system namespacing options (such as PrivateTmp=,
+ PrivateDevices=, ProtectSystem=, …) are used. This option is hence
+ primarily useful for services that do not use any of the other file
+ system namespacing options. One such service is systemd-udevd.service
+ wher this is now used by default.
+
+ * ConditionSecurity= gained a new value "uefi-secureboot" that is true
+ when the system is booted in UEFI "secure mode".
+
+ * A new unit "system-update-pre.target" is added, which defines an
+ optional synchronization point for offline system updates, as
+ implemented by the pre-existing "system-update.target" unit. It
+ allows ordering services before the service that executes the actual
+ update process in a generic way.
+
+ Contributions from: Adam Duskett, Alan Jenkins, Alessandro Casale,
+ Alexander Kurtz, Alex Gartrell, Anssi Hannula, Arnaud Rebillout, Brian
+ J. Murrell, Bruno Vernay, Chris Lamb, Chris Lesiak, Christian Brauner,
+ Christian Hesse, Christian Rebischke, Colin Guthrie, Daniel Dao, Daniel
+ Lin, Danylo Korostil, Davide Cavalca, David Tardon, Dimitri John
+ Ledkov, Dmitriy Geels, Douglas Christman, Elia Geretto, emelenas, Emil
+ Velikov, Evgeny Vereshchagin, Felipe Sateler, Feng Sun, Filipe
+ Brandenburger, Franck Bui, futpib, Giuseppe Scrivano, Guillem Jover,
+ guixxx, Hannes Reinecke, Hans de Goede, Harald Hoyer, Henrique Dante de
+ Almeida, Hiram van Paassen, Ian Miell, Igor Gnatenko, Ivan Shapovalov,
+ Iwan Timmer, James Cowgill, Jan Janssen, Jan Synacek, Jared Kazimir,
+ Jérémy Rosen, João Paulo Rechi Vita, Joost Heitbrink, Jui-Chi Ricky
+ Liang, Jürg Billeter, Kai-Heng Feng, Karol Augustin, Kay Sievers,
+ Krzysztof Nowicki, Lauri Tirkkonen, Lennart Poettering, Leonard König,
+ Long Li, Luca Boccassi, Lucas Werkmeister, Marcel Hoppe, Marc
+ Kleine-Budde, Mario Limonciello, Martin Jansa, Martin Wilck, Mathieu
+ Malaterre, Matteo F. Vescovi, Matthew McGinn, Matthias-Christian Ott,
+ Michael Biebl, Michael Olbrich, Michael Prokop, Michal Koutný, Michal
+ Sekletar, Mike Gilbert, Mikhail Kasimov, Milan Broz, Milan Pässler,
+ Mladen Pejaković, Muhammet Kara, Nicolas Boichat, Omer Katz, Paride
+ Legovini, Paul Menzel, Paul Milliken, Pavel Hrdina, Peter A. Bigot,
+ Peter D'Hoye, Peter Hutterer, Peter Jones, Philip Sequeira, Philip
+ Withnall, Piotr Drąg, Radostin Stoyanov, Ricardo Salveti de Araujo,
+ Ronny Chevalier, Rosen Penev, Rubén Suárez Alvarez, Ryan Gonzalez,
+ Salvo Tomaselli, Sebastian Reichel, Sergey Ptashnick, Sergio Lindo
+ Mansilla, Stefan Schweter, Stephen Hemminger, Stuart Hayes, Susant
+ Sahani, Sylvain Plantefève, Thomas H. P. Andersen, Tobias Jungel,
+ Tomasz Torcz, Vito Caputo, Will Dietz, Will Thompson, Wim van Mourik,
+ Yu Watanabe, Zbigniew Jędrzejewski-Szmek
+
+ — Berlin, 2018-06-22
+
CHANGES WITH 238:
* The MemoryAccounting= unit property now defaults to on. After
@@ -312,7 +688,7 @@ CHANGES WITH 237:
systemd.service_watchdogs= for controlling the same.
* Two new "log-level" and "log-target" options for systemd-analyze were
- addded that merge the now deprecated get-log-level, set-log-level and
+ added that merge the now deprecated get-log-level, set-log-level and
get-log-target, set-log-target pairs. The deprecated options are still
understood for backwards compatibility. The two new options print the
current value when no arguments are given, and set them when a
@@ -881,7 +1257,7 @@ CHANGES WITH 234:
(domain search list).
* systemd-networkd gained support for serving IPv6 address ranges using
- the Router Advertisment protocol. The new .network configuration
+ the Router Advertisement protocol. The new .network configuration
section [IPv6Prefix] may be used to configure the ranges to
serve. This is implemented based on a new, minimal, native server
implementation of RA.
@@ -1612,7 +1988,7 @@ CHANGES WITH 232:
counted multiple times, if it takes multiple references.
* sd-bus gained new API calls sd_bus_set_exit_on_disconnect() and
- sd_bus_get_exit_on_disconnect(). They may be used to to make a
+ sd_bus_get_exit_on_disconnect(). They may be used to make a
process using sd-bus automatically exit if the bus connection is
severed.
@@ -1943,7 +2319,7 @@ CHANGES WITH 231:
with future releases) that the components link to. This should
decrease systemd footprint both in memory during runtime and on
disk. Note that the shared library is not for public use, and is
- neither API not ABI stable, but is likely to change with every new
+ neither API nor ABI stable, but is likely to change with every new
released update. Packagers need to make sure that binaries
linking to libsystemd-shared.so are updated in step with the
library.
diff --git a/README b/README
index 4a561a65cb..2cde08c37e 100644
--- a/README
+++ b/README
@@ -161,7 +161,7 @@ REQUIREMENTS:
docbook-xsl (optional, required for documentation)
xsltproc (optional, required for documentation)
python-lxml (optional, required to build the indices)
- python, meson, ninja
+ python >= 3.4, meson >= 0.44, ninja
gcc, awk, sed, grep, m4, and similar tools
During runtime, you need the following additional
@@ -303,13 +303,12 @@ WARNINGS:
For more information on this issue consult
https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
- To run systemd under valgrind, compile with VALGRIND defined
- (e.g. CPPFLAGS='... -DVALGRIND=1' meson <options>) and have valgrind
- development headers installed (i.e. valgrind-devel or
- equivalent). Otherwise, false positives will be triggered by code which
- violates some rules but is actually safe. Note that valgrind generates
- nice output only on exit(), hence on shutdown we don't execve()
- systemd-shutdown.
+ To run systemd under valgrind, compile with meson option
+ -Dvalgrind=true and have valgrind development headers installed
+ (i.e. valgrind-devel or equivalent). Otherwise, false positives will be
+ triggered by code which violates some rules but is actually safe. Note
+ that valgrind generates nice output only on exit(), hence on shutdown
+ we don't execve() systemd-shutdown.
STABLE BRANCHES AND BACKPORTS
diff --git a/README.md b/README.md
index c122d01731..a57566834c 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,8 @@
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
[![Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
[![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)<br/>
-[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)<br/>
+[![Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)
## Details
diff --git a/TODO b/TODO
index 18acb9b363..ff1008accf 100644
--- a/TODO
+++ b/TODO
@@ -1,16 +1,8 @@
Bugfixes:
-* Should systemctl status \* work on all unit types, not just .service?
+* the error paths in usbffs_dispatch_ep() leak memory
-* Dangling symlinks of .automount unit files in .wants/ directories, set up
- automount points even when the original .automount file did not exist
- anymore. Only the .mount unit was still around.
-
-* ExecStart with unicode characters fails in strv_split_extract:
-
- [Service]
- Environment=ONE='one' "TWO='two two' too" THREE=
- ExecStart=/bin/python3 -c 'import sys;print(sys.argv)' $ONE $TWO $THREE
+* copy.c: set the right chattrs before copying files and others after
External:
@@ -22,14 +14,102 @@ Janitorial Clean-ups:
* Rearrange tests so that the various test-xyz.c match a specific src/basic/xyz.c again
+* copy.c: set the right chattrs before copying files and others after
+
+* rework mount.c and swap.c to follow proper state enumeration/deserialization
+ semantics, like we do for device.c now
+
Features:
+* the stop-when-unneded feature should be reworked: there should be a queue of
+ units, and we should only enqeueu stop jobs from a defer event that processes
+ queue instead of right-away when we assume that a unit is now unneeded.
+
+* When reloading configuration PID 1 should reset all its properties to the
+ original defaults before calling parse_config()
+
+* Add OnTimezoneChange= and OnTimeChange= stanzas to .timer units in order to
+ schedule events based on time and timezone changes.
+
+* nspawn: greater control over selinux label?
+
+* cgroups: figure out if we can somehow communicate in a cleaner way whether a
+ systemd instance not running in the cgroup root shall or shall not manage the
+ attributes of its top-level cgroup. Currently it assumes it manages all, but
+ then might get EPERM due to permission porblems/userns, which is OK, but this
+ should be revisited to make clearer and also work if the payload systemd runs
+ with full privs and without userns.
+
+* portables: introduce a new unit file directory /etc/systemd/system.attached/
+ or so, where we attach portable services to
+
+* cgroups: use inotify to get notified when somebody else modifies cgroups
+ owned by us, then log a friendly warning.
+
+* beef up log.c with support for stripping ANSI sequences from strings, so that
+ it is OK to include them in log strings. This would be particularly useful so
+ that our log messages could contain clickable links for example for unit
+ files and suchlike we operate on.
+
+* introduce a new SystemCallFilters= group called "@system-service" with a
+ sensible default set for system services, then make use of them in portable
+ profiles
+
+* add support for "portablectl attach http://foobar.com/waaa.raw (i.e. importd integration)
+
+* add attach --enable and attach --now (for attach+enable+start)
+
+* sync dynamic uids/gids between host+portable srvice (i.e. if DynamicUser=1 is set for a service, make sure that the
+ selected user is resolvable in the service even if it ships its own /etc/passwd)
+
+* Fix DECIMAL_STR_MAX or DECIMAL_STR_WIDTH. One includes a trailing NUL, the
+ other doesn't. What a desaster. Probably to exclude it. Also
+ DECIMAL_STR_WIDTH should probably add an extra "-" into account for negative
+ numbers.
+
+* Check that users of inotify's IN_DELETE_SELF flag are using it properly, as
+ usually IN_ATTRIB is the right way to watch deleted files, as the former only
+ fires when a file is actually removed from disk, i.e. the link count drops to
+ zero and is not open anymore, while the latter happens when a file is
+ unlinked from any dir.
+
+* port systemctl, systemd-inhibit, busctl, … over to format-table.[ch]'s table formatters
+
+* pid1: lock image configured with RootDirectory=/RootImage= using the usual nspawn semantics while the unit is up
+
+* add --vacuum-xyz options to coredumpctl, matching those journalctl already has.
+
+* SuccessExitStatus= and friends should probably also accept symbolic exit
+ codes names, i.e. error codes from the list maintained in exit-codes.[ch]
+
+* introduce Ephemeral= unit file switch, that creates an ephemeral copy of all
+ files and directories that are left writable for a unit, and which are
+ removed after the unit goes down again. A bit like --ephemeral for
+ systemd-nspawn but for system services. If used together with RootImage= this
+ should reflink the image file itself.
+
+ Related: add Ephemeral=<path1> <path2> … which would allow marking
+ specific paths only like this.
+
+* add CopyFile= or so as unit file setting that may be used to copy files or
+ directory trees from the host to te services RootImage= and RootDirectory=
+ environment. Which we can use for /etc/machine-id and in particular
+ /etc/resolv.conf. Should be smart and do something useful on read-only
+ images, for example fallback to read-only bind mounting the file instead.
+
+* nspawn's console TTY should be allocated from within the container, not
+ mounted in from the outside
+
+* show invocation ID in systemd-run output
+
+* bypass SIGTERM state in unit files if KillSignal is SIGKILL
+
+* tree-wide: ensure we always block the signals we hook into with
+ sd_event_add_signal() first
+
* add proper dbus APIs for the various sd_notify() commands, such as MAINPID=1
and so on, which would mean we could report errors and such.
-* nss-systemd: implement enumeration, that shows all dynamic users plus the
- synthesized ones if necessary, so that "getent passwd" shows useful data.
-
* teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4
project quota
@@ -126,10 +206,6 @@ Features:
* In DynamicUser= mode: before selecting a UID, use disk quota APIs on relevant
disks to see if the UID is already in use.
-* add dissect_image_warn() as a wrapper around dissect_image() that prints
- friendly log messages for the returned errors, so that we don't have to
- duplicate that in nspawn, systemd-dissect and PID 1.
-
* add "systemctl wait" or so, which does what "systemd-run --wait" does, but
for all units. It should be both a way to pin units into memory as well as a
wait to retrieve their exit data.
@@ -276,8 +352,6 @@ Features:
* rework fopen_temporary() to make use of open_tmpfile_linkable() (problem: the
kernel doesn't support linkat() that replaces existing files, currently)
-* check if DeviceAllow= should split first, resolve specifiers later
-
* transient units: don't bother with actually setting unit properties, we
reload the unit file anyway
@@ -334,11 +408,6 @@ Features:
* networkd/udev: implement SR_IOV configuration in .link files:
http://lists.freedesktop.org/archives/systemd-devel/2015-January/027451.html
-* Rework systemctl's GetAll property parsing to use the generic bus_map_all_properties() API
-
-* Port various tools to make use of verbs.[ch], where applicable: busctl,
- coredumpctl, hostnamectl, localectl, timedatectl
-
* hostnamectl: show root image uuid
* sysfs set api in libudev is not const
@@ -468,7 +537,6 @@ Features:
* transient units:
- add field to transient units that indicate whether systemd or somebody else saves/restores its settings, for integration with libvirt
- - ensure scope units may be started only a single time
* Automatically configure swap partition to use for hibernation by looking for largest swap partition on the root disk?
@@ -514,7 +582,7 @@ Features:
- document chaining of signal handler for SIGCHLD and child handlers
- define more intervals where we will shift wakeup intervals around in, 1h, 6h, 24h, ...
- generate a failure of a default event loop is executed out-of-thread
- - maybe add support for inotify events
+ - maybe add support for inotify events (which we can do safely now, with O_PATH)
* investigate endianness issues of UUID vs. GUID
@@ -528,8 +596,7 @@ Features:
* maybe add a generator that looks for "systemd.run=" on the kernel cmdline for container usercases...
* test/:
- - add 'set -e' to scripts in test/
- - make stuff in test/ work with separate output dir
+ - add unit tests for config_parse_device_allow()
* seems that when we follow symlinks to units we prefer the symlink
destination path over /etc and /usr. We should not do that. Instead
@@ -578,7 +645,6 @@ Features:
- logind: wakelock/opportunistic suspend support
- Add pretty name for seats in logind
- logind: allow showing logout dialog from system?
- - we should probably handle SIGTERM/SIGINT to not leave dot files around, just in case
- session scopes/user unit: add RequiresMountsFor for the home directory of the user
- add Suspend() bus calls which take timestamps to fix double suspend issues when somebody hits suspend and closes laptop quickly.
- if pam_systemd is invoked by su from a process that is outside of a
@@ -593,10 +659,6 @@ Features:
logout dialog. If it is pressed for 1s, do the usual
shutdown. Inspiration are Macs here.
- expose "Locked" property on logind sesison objects
- - given that logind now lets PID 1 do all nasty work, we can
- probably reduce the capability set it retains substantially.
- (we need CAP_SYS_ADMIN for drmSetMaster(), so maybe not worth it)
- - expose orientation sensors and tablet mode through logind
- maybe allow configuration of the StopTimeout for session scopes
- rename session scope so that it includes the UID. THat way
the session scope can be arranged freely in slices and we don't have
@@ -653,8 +715,6 @@ Features:
lazily. Encode just enough information in the file name, so that we
do not have to open it to know that it is not interesting for us, for
the most common operations.
- - journal-or-kmsg is currently broken? See reverted
- commit 4a01181e460686d8b4a543b1dfa7f77c9e3c5ab8.
- man: document that corrupted journal files is nothing to act on
- rework journald sigbus stuff to use mutex
- Set RLIMIT_NPROC for systemd-journal-xyz, and all other of our
@@ -710,6 +770,7 @@ Features:
- timer units should get the ability to trigger when:
o CLOCK_REALTIME makes jumps (TFD_TIMER_CANCEL_ON_SET)
o DST changes
+ o timezone changes
- Modulate timer frequency based on battery state
* add libsystemd-password or so to query passwords during boot using the password agent logic
@@ -774,8 +835,6 @@ Features:
* hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it
https://bugs.freedesktop.org/show_bug.cgi?id=54712
-* create /sbin/init symlinks from the build system
-
* add a dependency on standard-conf.xml and other included files to man pages
* MountFlags=shared acts as MountFlags=slave right now.
diff --git a/catalog/meson.build b/catalog/meson.build
index 69f970388a..1b13150894 100644
--- a/catalog/meson.build
+++ b/catalog/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
in_files = '''
systemd.bg.catalog
diff --git a/catalog/systemd.be.catalog.in b/catalog/systemd.be.catalog.in
index 28de086be7..5011ea268d 100644
--- a/catalog/systemd.be.catalog.in
+++ b/catalog/systemd.be.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2015, 2016 Viktar Vaŭčkievič
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2015, 2016 Viktar Vaŭčkievič
# Message catalog for systemd's own messages
# Belarusian translation
diff --git a/catalog/systemd.be@latin.catalog.in b/catalog/systemd.be@latin.catalog.in
index dc5f9b731f..6a8b092669 100644
--- a/catalog/systemd.be@latin.catalog.in
+++ b/catalog/systemd.be@latin.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2015, 2016 Viktar Vaŭčkievič
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2015, 2016 Viktar Vaŭčkievič
# Message catalog for systemd's own messages
# Belarusian Latin translation
diff --git a/catalog/systemd.bg.catalog.in b/catalog/systemd.bg.catalog.in
index 202b192b30..64d616f381 100644
--- a/catalog/systemd.bg.catalog.in
+++ b/catalog/systemd.bg.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2016 Alexander Shopov <ash@kambanaria.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/>.
+# Copyright © 2016 Alexander Shopov <ash@kambanaria.org>
# Message catalog for systemd's own messages
diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in
index 118fe860fe..f1bddc6f7d 100644
--- a/catalog/systemd.catalog.in
+++ b/catalog/systemd.catalog.in
@@ -1,21 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# 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/>.
# Message catalog for systemd's own messages
diff --git a/catalog/systemd.da.catalog.in b/catalog/systemd.da.catalog.in
index 69446fb7f0..4e2bec8a0f 100644
--- a/catalog/systemd.da.catalog.in
+++ b/catalog/systemd.da.catalog.in
@@ -1,21 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# 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/>.
# Message catalog for systemd's own messages
# Danish translation
diff --git a/catalog/systemd.de.catalog.in b/catalog/systemd.de.catalog.in
index 8fdedafc09..d10111b0d6 100644
--- a/catalog/systemd.de.catalog.in
+++ b/catalog/systemd.de.catalog.in
@@ -1,21 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# 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/>.
-- fc2e22bc6ee647b6b90729ab34a250b1
Subject: Speicherabbild für Prozess @COREDUMP_PID@ (@COREDUMP_COMM) generiert
diff --git a/catalog/systemd.fr.catalog.in b/catalog/systemd.fr.catalog.in
index 6df3b00f3d..156b1a37dc 100644
--- a/catalog/systemd.fr.catalog.in
+++ b/catalog/systemd.fr.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2013-2016 Sylvain Plantefève
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2013-2016 Sylvain Plantefève
# Message catalog for systemd's own messages
# French translation
diff --git a/catalog/systemd.hr.catalog.in b/catalog/systemd.hr.catalog.in
index f6e238e7c1..c4808b4c7d 100644
--- a/catalog/systemd.hr.catalog.in
+++ b/catalog/systemd.hr.catalog.in
@@ -1,21 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# 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/>.
# Message catalog for systemd's own messages
# Croatian translation
diff --git a/catalog/systemd.hu.catalog.in b/catalog/systemd.hu.catalog.in
index 9f5e87893b..6c6d7e7934 100644
--- a/catalog/systemd.hu.catalog.in
+++ b/catalog/systemd.hu.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2016 Gabor Kelemen
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2016 Gabor Kelemen
# Message catalog for systemd's own messages
diff --git a/catalog/systemd.it.catalog.in b/catalog/systemd.it.catalog.in
index df1e225eaf..4fd1f2a933 100644
--- a/catalog/systemd.it.catalog.in
+++ b/catalog/systemd.it.catalog.in
@@ -1,21 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2013 Daniele Medri
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2013 Daniele Medri
# Message catalog for systemd's own messages
diff --git a/catalog/systemd.ko.catalog.in b/catalog/systemd.ko.catalog.in
index e57818081d..fc0faad02c 100644
--- a/catalog/systemd.ko.catalog.in
+++ b/catalog/systemd.ko.catalog.in
@@ -1,21 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# 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/>.
# Message catalog for systemd's own messages
# Korean translation
diff --git a/catalog/systemd.pl.catalog.in b/catalog/systemd.pl.catalog.in
index 3352a59a27..998894bd0a 100644
--- a/catalog/systemd.pl.catalog.in
+++ b/catalog/systemd.pl.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2014-2017 Piotr Drąg
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2014-2017 Piotr Drąg
# Message catalog for systemd's own messages
# Polish translation
diff --git a/catalog/systemd.pt_BR.catalog.in b/catalog/systemd.pt_BR.catalog.in
index 6a30dd3e10..db1cb03198 100644
--- a/catalog/systemd.pt_BR.catalog.in
+++ b/catalog/systemd.pt_BR.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2015 Rafael Ferreira (translation)
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2015 Rafael Ferreira (translation)
# Catálogo de mensagens para as mensagens do próprio systemd
diff --git a/catalog/systemd.ru.catalog.in b/catalog/systemd.ru.catalog.in
index be6410b508..645edaa922 100644
--- a/catalog/systemd.ru.catalog.in
+++ b/catalog/systemd.ru.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2013-2017 Sergey Ptashnick
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2013-2017 Sergey Ptashnick
# Message catalog for systemd's own messages
# Russian translation
diff --git a/catalog/systemd.sr.catalog.in b/catalog/systemd.sr.catalog.in
index 1d494ffce2..f5746715a4 100644
--- a/catalog/systemd.sr.catalog.in
+++ b/catalog/systemd.sr.catalog.in
@@ -1,21 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# 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/>.
# Message catalog for systemd's own messages
# Serbian translation
diff --git a/catalog/systemd.zh_CN.catalog.in b/catalog/systemd.zh_CN.catalog.in
index 92e32200de..fa58448acf 100644
--- a/catalog/systemd.zh_CN.catalog.in
+++ b/catalog/systemd.zh_CN.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2015 Boyuan Yang
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2015 Boyuan Yang
# Message catalog for systemd's own messages
# Simplified Chinese translation
diff --git a/catalog/systemd.zh_TW.catalog.in b/catalog/systemd.zh_TW.catalog.in
index 66db58d162..17bd2bc9af 100644
--- a/catalog/systemd.zh_TW.catalog.in
+++ b/catalog/systemd.zh_TW.catalog.in
@@ -1,22 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2015 Jeff Huang
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2015 Jeff Huang
# Message catalog for systemd's own messages
# Traditional Chinese translation
diff --git a/coccinelle/bool-cast.cocci b/coccinelle/bool-cast.cocci
new file mode 100644
index 0000000000..051ccb9417
--- /dev/null
+++ b/coccinelle/bool-cast.cocci
@@ -0,0 +1,12 @@
+@@
+bool b;
+expression y;
+@@
+- b = !!(y);
++ b = y;
+@@
+bool b;
+expression y;
+@@
+- b = !!y;
++ b = y;
diff --git a/coccinelle/div-round-up.cocci b/coccinelle/div-round-up.cocci
new file mode 100644
index 0000000000..a0c6df9801
--- /dev/null
+++ b/coccinelle/div-round-up.cocci
@@ -0,0 +1,20 @@
+@@
+expression x, y;
+@@
+- ((x + y - 1) / y)
++ DIV_ROUND_UP(x, y)
+@@
+expression x, y;
+@@
+- ((x + (y - 1)) / y)
++ DIV_ROUND_UP(x, y)
+@@
+expression x, y;
+@@
+- (x + y - 1) / y
++ DIV_ROUND_UP(x, y)
+@@
+expression x, y;
+@@
+- (x + (y - 1)) / y
++ DIV_ROUND_UP(x, y)
diff --git a/coccinelle/dup-fcntl.cocci b/coccinelle/dup-fcntl.cocci
new file mode 100644
index 0000000000..ef13564282
--- /dev/null
+++ b/coccinelle/dup-fcntl.cocci
@@ -0,0 +1,5 @@
+@@
+expression fd;
+@@
+- dup(fd)
++ fcntl(fd, F_DUPFD, 3)
diff --git a/coccinelle/empty-or-root.cocci b/coccinelle/empty-or-root.cocci
new file mode 100644
index 0000000000..bf2f614da6
--- /dev/null
+++ b/coccinelle/empty-or-root.cocci
@@ -0,0 +1,10 @@
+@@
+expression s;
+@@
+- (isempty(s) || path_equal(s, "/"))
++ empty_or_root(s)
+@@
+expression s;
+@@
+- (!isempty(s) && !path_equal(s, "/"))
++ !empty_or_root(s)
diff --git a/coccinelle/flags-set.cocci b/coccinelle/flags-set.cocci
new file mode 100644
index 0000000000..1a70717e76
--- /dev/null
+++ b/coccinelle/flags-set.cocci
@@ -0,0 +1,15 @@
+@@
+expression x, y;
+@@
+- ((x) & (y)) == (y)
++ FLAGS_SET(x, y)
+@@
+expression x, y;
+@@
+- (x & (y)) == (y)
++ FLAGS_SET(x, y)
+@@
+expression x, y;
+@@
+- ((x) & y) == y
++ FLAGS_SET(x, y)
diff --git a/coccinelle/o-ndelay.occi b/coccinelle/o-ndelay.cocci
index 669424a054..669424a054 100644
--- a/coccinelle/o-ndelay.occi
+++ b/coccinelle/o-ndelay.cocci
diff --git a/coccinelle/run-coccinelle.sh b/coccinelle/run-coccinelle.sh
index de23546f19..22ab66d3dd 100755
--- a/coccinelle/run-coccinelle.sh
+++ b/coccinelle/run-coccinelle.sh
@@ -1,10 +1,27 @@
#!/bin/bash -e
-for SCRIPT in ${@-*.cocci} ; do
- echo "--x-- Processing: spatch --sp-file $SCRIPT --dir $(pwd)/.. --x--"
+top="$(git rev-parse --show-toplevel)"
+files="$(git ls-files ':/*.[ch]')"
+args=
+
+case "$1" in
+ -i)
+ args="$args --in-place"
+ shift
+ ;;
+esac
+
+if ! parallel -h >/dev/null; then
+ echo 'Please install GNU parallel (package "parallel")'
+ exit 1
+fi
+
+for SCRIPT in ${@-$top/coccinelle/*.cocci} ; do
+ echo "--x-- Processing $SCRIPT --x--"
TMPFILE=`mktemp`
- spatch --sp-file $SCRIPT --dir $(pwd)/.. 2> "$TMPFILE" || cat "$TMPFILE"
- rm "$TMPFILE"
- echo "--x-- Processed: spatch --sp-file $SCRIPT --dir $(pwd)/.. --x--"
- echo ""
+ echo "+ spatch --sp-file $SCRIPT $args ..."
+ parallel --halt now,fail=1 --keep-order --noswap --max-args=20 \
+ spatch --sp-file $SCRIPT $args ::: $files \
+ 2>"$TMPFILE" || cat "$TMPFILE"
+ echo -e "--x-- Processed $SCRIPT --x--\n"
done
diff --git a/coccinelle/take-fd.cocci b/coccinelle/take-fd.cocci
new file mode 100644
index 0000000000..ba242483cd
--- /dev/null
+++ b/coccinelle/take-fd.cocci
@@ -0,0 +1,14 @@
+@@
+local idexpression p;
+expression q;
+@@
+- p = q;
+- q = -1;
+- return p;
++ return TAKE_FD(q);
+@@
+expression p, q;
+@@
+- p = q;
+- q = -1;
++ p = TAKE_FD(q);
diff --git a/coccinelle/take-ptr.cocci b/coccinelle/take-ptr.cocci
new file mode 100644
index 0000000000..0cebe81575
--- /dev/null
+++ b/coccinelle/take-ptr.cocci
@@ -0,0 +1,14 @@
+@@
+local idexpression p;
+expression q;
+@@
+- p = q;
+- q = NULL;
+- return p;
++ return TAKE_PTR(q);
+@@
+expression p, q;
+@@
+- p = q;
+- q = NULL;
++ p = TAKE_PTR(q);
diff --git a/doc/BOOT_LOADER_SPECIFICATION.md b/doc/BOOT_LOADER_SPECIFICATION.md
new file mode 100644
index 0000000000..dc67f2ffc8
--- /dev/null
+++ b/doc/BOOT_LOADER_SPECIFICATION.md
@@ -0,0 +1,140 @@
+# The Boot Loader Specification
+
+_TL;DR: Currently there's little cooperation between multiple distributions in dual-boot (or triple, ... multi-boot) setups, and we'd like to improve this situation by getting everybody to commit to a single boot configuration format that is based on drop-in files, and thus is robust, simple, works without rewriting configuration files and is free of namespace clashes._
+
+The Boot Loader Specification defines a scheme how different operating systems can cooperatively manage a boot loader configuration directory, that accepts drop-in files for boot menu items that are defined in a format that is shared between various boot loader implementations, operating systems, and userspace programs. The target audience for this specification is:
+
+* Boot loader developers, to write a boot loader that directly reads its configuration at runtime from these drop-in snippets
+* Distribution and Core OS developers, in order to create these snippets at OS/kernel package installation time
+* UI developers, for implementing a user interface that discovers the available boot options
+* OS Installer developers, for setting up the initial drop-in directory
+
+## Why is there a need for this specification?
+
+Of course, without this specification things already work mostly fine. But here's why we think this specification is needed:
+
+* To make the boot more robust, as no explicit rewriting of configuration files is required any more
+* To improve dual-boot scenarios. Currently, multiple Linux installations tend to fight over which boot loader becomes the primary one in possession of the MBR, and only that one installation can then update the boot loader configuration of it freely. Other Linux installs have to be manually configured to never touch the MBR and instead install a chain-loaded boot loader in their own partition headers. In this new scheme as all installations share a loader directory no manual configuration has to take place, and all participants implicitly cooperate due to removal of name collisions and can install/remove their own boot menu entries at free will, without interfering with the entries of other installed operating systems.
+* Drop-in directories are otherwise now pretty ubiquitous on Linux as an easy way to extend configuration without having to edit, regenerate or manipulate configuration files. For the sake of uniformity we should do the same for extending the boot menu.
+* Userspace code can sanely parse boot loader configuration which is essential with modern BIOSes which do not necessarily initialize USB keyboards anymore during boot, which makes boot menus hard to reach for the user. If userspace code can parse the boot loader configuration, too, this allows for UIs that can select a boot menu item to boot into, before rebooting the machine, thus not requiring interactivity during early boot.
+* To unify and thus simplify configuration of the various boot loaders around, which makes configuration of the boot loading process easier for users, administrators and developers alike
+* For boot loaders with configuration _scripts_ such as grub2, adopting this spec allows for mostly static scripts that are generated only once at first installation, but then do not need to be updated anymore as that is done via drop-in files exclusively.
+
+## Why not simply rely on the EFI boot menu logic?
+
+The EFI specification provides a boot options logic that can offer similar functionality. Here's why we think that it is not enough for our uses:
+
+* The various EFI implementations implement the boot order/boot item logic to different levels. Some firmware implementations do not offer a boot menu at all and instead unconditionally follow the EFI boot order, booting the first item that is working.
+* If the firmware setup is used to reset all data usually all EFI boot entries are lost, making the system entirely unbootable, as the firmware setups generally do not offer a UI to define additional boot items. By placing the menu item information on disk it is always available, regardless if the BIOS setup data is lost.
+* Harddisk images should be moveable between machines and be bootable without requiring explicit EFI variables to be set. This also requires that the list of boot options is defined on disk, and not in EFI variables alone.
+* EFI is not universal yet (especially on non-x86 platforms), this specification is useful both for EFI and non-EFI boot loaders.
+* Many EFI systems disable USB support during early boot to optimize boot times, thus making keyboard input unavailable in the EFI menu. It is thus useful if the OS UI has a standardized way to discover available boot options which can be booted to.
+
+## Technical Details
+
+Everything described below is located on a placeholder file system `$BOOT`. The installer program should pick `$BOOT` according to the following rules:
+
+* On disks with MBR disk labels
+ * If the OS is installed on a disk with MBR disk label, and a partition with the MBR type id of 0xEA already exists it should be used as `$BOOT`.
+ * Otherwise, if the the OS is installed on a disk with MBR disk label, a new partition with MBR type id of 0xEA shall be created, of a suitable size (let's say 500MB), and it should be used as `$BOOT`.
+* On disks with GPT disk labels
+ * If the OS is installed on a disk with GPT disk label, and a partition with the GPT type GUID of bc13c2ff-59e6-4262-a352-b275fd6f7172 already exists, it should be used as `$BOOT`.
+ * Otherwise, if the OS is installed on a disk with GPT disk label, and an ESP partition (i.e. with the GPT type UID of c12a7328-f81f-11d2-ba4b-00a0c93ec93b) already exists and is large enough (let's say 250MB) and otherwise qualifies, it should be used as `$BOOT`.
+ * Otherwise, if the OS is installed on a disk with GPT disk label, and if the ESP partition already exists but is too small, a new suitably sized (let's say 500MB) partition with GPT type GUID of bc13c2ff-59e6-4262-a352-b275fd6f7172 shall be created and it should be used as `$BOOT`.
+ * Otherwise, if the OS is installed on a disk with GPT disk label, and no ESP partition exists yet, a new suitably sized (let's say 500MB) ESP should be created and should be used as `$BOOT`.
+
+This placeholder file system shall be determined during _installation time_, and an fstab entry maybe be created. It should be mounted to either /boot or /efi. Additional locations like /boot/efi, with /boot being a separate file system, might be supported by implementations. This is not recommended because the mounting of `$BOOT` is then dependent on and requires the mounting of the intermediate file system.
+
+**Note:** _`$BOOT` should be considered **shared** among all OS installations of a system. Instead of maintaining one `$BOOT` per installed OS (as `/boot` was traditionally handled), all installed OS share the same place to drop in their boot-time configuration._
+
+`$BOOT` must be a VFAT (16 or 32) file system. Other file system types should not be used. Applications accessing `$BOOT` should hence not assume that fancier file system features such as symlinks, hardlinks, access control or case sensitivity are supported.
+
+### Boot loader specification entries
+
+We define two directories below `$BOOT`:
+
+* `$BOOT/loader/` is the directory containing all files defined by this specification
+* `$BOOT/loader/entries/` is the directory containing the drop-in snippets. This directory contains one `.conf` file for each boot menu item.
+
+**Note:** _In all cases the /loader directory should be located directly in the root of the file system. Specifically, if `$BOOT` is the ESP, then /loader directory should be located directly in the root directory of the ESP, and not in the EFI/ subdirectory._
+
+Inside the `$BOOT/loader/entries/` directory each OS vendor may drop one or more configuration snippets with the suffix ".conf", one for each boot menu item. The file name of the file is used for identification of the boot item, but shall never be presented to the user in the UI. The file name may be chosen freely but should be unique enough to avoid clashes between OS installations. More specifically it is suggested to include the machine ID (`/etc/machine-id` or the D-Bus machine ID for OSes that lack `/etc/machine-id`), the kernel version (as returned by `uname -r`) and an OS identifier (The ID field of `/etc/os-release`). Example: `$BOOT/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf`.
+
+These configuration snippets shall be Unix-style text files (i.e. line separation with a single newline character), in the UTF-8 encoding. The configuration snippets are loosely inspired on Grub1's configuration syntax. Lines beginning with '#' shall be ignored and used for commenting. The first word of a line is used as key, and shall be separated by a space from its value. The following keys are known:
+
+* `title` shall contain a human readable title string for this menu item. This will be displayed in the boot menu for the item. It is a good idea to initialize this from the `PRETTY_NAME` of `/etc/os-release`. This name should be descriptive and does not have to be unique. If a boot loader discovers two entries with the same title it is a good idea to show more than just the raw title in the UI, for example by appending the `version` field. This field is optional. Example: "Fedora 18 (Spherical Cow)".
+* `version` shall contain a human readable version string for this menu item. This is usually the kernel version and is intended for use by OSes to install multiple kernel versions at the same time with the same `title` field. This field shall be in a syntax that is useful for Debian-style version sorts, so that the boot loader UI can determine the newest version easily and show it first or preselect it automatically. This field is optional. Example: `3.7.2-201.fc18.x86_64`
+* `machine-id` shall contain the machine ID of the OS `/etc/machine-id`. This is useful for boot loaders and applications to filter out boot entries, for example to show only a single newest kernel per OS, or to group items by OS, or to maybe filter out the currently booted OS in UIs that want to show only other installed operating systems. This ID shall be formatted as 32 lower case hexadecimal characters (i.e. without any UUID formatting). This key is optional. Example: `4098b3f648d74c13b1f04ccfba7798e8`
+* `linux` refers to the kernel to spawn, and shall be a path relative to the `$BOOT` directory. It is recommended that every distribution creates a machine id and version specific subdirectory below `$BOOT` and places its kernels and initial RAM disk images there. Example: `/6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux`.
+* `initrd` refers to the initrd to use when executing the kernel. This also shall be a path relative to the `$BOOT` directory. This key is optional. This key may appear more than once in which case all specified images are used, in the order they are listed. Example: `6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd`
+* `efi` to spawn arbitrary EFI programs. This also takes a path relative to `$BOOT`. This key is only available on EFI systems.
+* `options` shall contain kernel parameters to pass to the Linux kernel to spawn. This key is optional.
+* `devicetree` refers to the binary device tree to use when executing the
+kernel. This also shall be a path relative to the `$BOOT` directory. This
+key is optional. Example: `6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.armv7hl/tegra20-paz00.dtb`
+* `architecture` refers to the UEFI architecture this entry is defined for. If specified and this does not match the local UEFI system architecture the entry is hidden.
+
+Each configuration drop-in snippet must include at least a `linux` or an `efi` key, and is otherwise not valid. Here's an example for a complete drop-in file:
+
+ # /boot/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf
+ title Fedora 19 (Rawhide)
+ version 3.8.0-2.fc19.x86_64
+ machine-id 6a9857a393724b7a981ebb5b8495b9ea
+ options root=UUID=6d3376e4-fc93-4509-95ec-a21d68011da2
+ linux /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux
+ initrd /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd
+
+On EFI systems all kernel images shall be EFI images. In order to be compatible with EFI systems it is highly recommended only to install EFI kernel images, even on non-EFI systems, if that's applicable and supported on the specific architecture.
+
+Note that these configuration snippets may only reference kernels (and EFI programs) that reside on the same file system as the configuration snippets, i.e. everything referenced must be contained in the same file system. This is by design, as referencing other partitions or devices would require a non-trivial language for denoting device paths. If kernels/initrds are to be read from other partitions/disks the boot loader can do this in its own native configuration, using its own specific device path language, and this is out of focus for this specification. More specifically, on non-EFI systems configuration snippets following this specification cannot be used to spawn other operating systems (such as Windows).
+
+### Unified kernel images
+
+A unified kernel image is a single UEFI executable combining an UEFI stub loader, a kernel image, an initramfs image, and the kernel command line. See the description of the `--uefi` option in [dracut(8)](http://man7.org/linux/man-pages/man8/dracut.8.html). Such images will be searched for under `$BOOT/EFI/Linux`, and must have the extension `.efi`.
+
+A valid unified kernel image must contain two PE sections:
+
+* `.cmdline` section with the kernel command line
+* `.osrel` section with an embedded copy of the [os-release](https://www.freedesktop.org/software/systemd/man/os-release.html) file describing the image
+
+The `PRETTY_NAME=` and `VERSION_ID=` fields in the embedded os-release file are used the same as `title` and `version` in the "boot loader specification" entries. The `.cmdline` section is used instead of the `options` field. `linux` and `initrd` fields are not necessary, and there is no counterpart for the `machine-id` field.
+
+Any such images shall be added to the list of valid boot entries.
+
+### Additional notes
+
+Note that these configurations snippets do not need to be the only configuration source for a boot loader. It may extend this list of entries with additional items from other configuration files (for example its own native configuration files) or automatically detected other entries without explicit configuration.
+
+To make this explicitly clear: this specification is designed with "free" operating systems in mind, starting Windows or MacOS is out of focus with these configuration snippets, use boot-loader specific solutions for that. In the text above, if we say "OS" we hence imply "free", i.e. primarily Linux (though this could be easily be extended to the BSDs and whatnot).
+
+Note that all paths used in the configuration snippets use a Unix-style "/" as path separator. This needs to be converted to an EFI-style "\" separator in EFI boot loaders.
+
+
+## Logic
+
+A _boot loader_ needs a file system driver to discover and read `$BOOT`, then simply reads all files `$BOOT/loader/entries/*.conf`, and populates its boot menu with this. It then extends this with any unified kernel images found in `$BOOT/EFI/Linux`. It may also add additional entries, for example "Reboot into firmware". Optionally it may sort the menu based on the `machine-id` and `version` fields, and possibly others. It uses the file name to identify specific items, for example in case it supports storing away default entry information somewhere. A boot loader should generally not modify these files.
+
+For "boot loader specification" entries, the _kernel package installer_ installs the kernel and initrd images to `$BOOT` (it is recommended to place these files in a vendor and OS and installation specific directory) and then generates a configuration snippet for it, placing this in `$BOOT/loader/entries/xyz.conf`, with xyz as concatenation of machine id and version information (see above). The files created by a kernel package are private property of the kernel package, and should be removed along with it.
+
+For "unified kernel images", the _kernel install_ creates the combined image and drops it into `$BOOT/EFI/Linux`. This file is also private property of the kernel package, and should be removed along with it.
+
+A _UI application_ intended to show available boot options shall operate similar to a boot loader, but might apply additional filters, for example by filtering out the booted OS via the machine ID, or by suppressing all but the newest kernel versions.
+
+An _OS installer_ picks the right place for `$BOOT` as defined above (possibly creating a partition and file system for it), and pre-creates the `/loader/entries/` directory in it. It then installs an appropriate boot loader that can read these snippets. Finally it installs one or more kernel packages.
+
+
+## Out of Focus
+
+There are a couple of items that are out of focus for this specifications:
+
+* If userspace can figure out the available boot options, then this is only useful so much: we'd still need to come up with a way how userspace could communicate to the boot loader the default boot loader entry temporarily or persistently. Defining a common scheme for this is certainly a good idea, but out of focus for this specifications.
+* This specifications is just about "Free" Operating systems. Hooking in other operating systems (like Windows, MacOS) into the boot menu is a different story, and should probably happen outside of this specification. For example, boot loaders might choose to detect other available OSes dynamically at runtime without explicit configuration (like <strike>Gummiboot</strike> systemd-boot does it), or via native configuration (for example via explicit Grub2 configuration generated once at installation).
+* This specification leaves undefined what to do about systems which are upgraded from an OS that does not implement this specification. As the previous boot loader logic was largely handled by in distribution-specific ways we probably should leave the upgrade path (and whether there actually is one) to the distributions. The simplest solution might be to simply continue with the old scheme for old installations and use this new scheme only for new installations.
+
+
+## Links
+
+[systemd-boot(7)](https://www.freedesktop.org/software/systemd/man/systemd-boot.html)<br>
+[bootctl(1)](https://www.freedesktop.org/software/systemd/man/bootctl.html)
+
+[Obsolete patch adding Boot Loader Specification support to GNU grub 2](http://pkgs.fedoraproject.org/cgit/grub2.git/tree/0460-blscfg-add-blscfg-module-to-parse-Boot-Loader-Specif.patch?h=f20)
diff --git a/doc/CGROUP_DELEGATION.md b/doc/CGROUP_DELEGATION.md
index 619c871212..63d9d41b10 100644
--- a/doc/CGROUP_DELEGATION.md
+++ b/doc/CGROUP_DELEGATION.md
@@ -9,7 +9,7 @@ what systemd has to offer there. Here's a bit of documentation about the
concepts and interfaces involved with this.
What's described here has been part of systemd and documented since v205
-times. However, it has been updated and improved substantially since, even
+times. However, it has been updated and improved substantially, even
though the concepts stayed mostly the same. This is an attempt to provide more
comprehensive up-to-date information about all this, particular in light of the
poor implementations of the components interfacing with systemd of current
@@ -42,7 +42,7 @@ to have processes directly attached to a cgroup that also has child cgroups and
vice versa. A cgroup is either an inner node or a leaf node of the tree, and if
it's an inner node it may not contain processes directly, and if it's a leaf
node then it may not have child cgroups. (Note that there are some minor
-exceptions to this rule, though. i.e. the root cgroup is special and allows
+exceptions to this rule, though. E.g. the root cgroup is special and allows
both processes and children — which is used in particular to maintain kernel
threads.)
@@ -67,14 +67,14 @@ root can do anything, modulo SELinux and friends), but if you ignore it you'll
be in constant pain as various pieces of software will fight over cgroup
ownership.
-Note that cgroupsv1 is currently the most deployed implementation of all of
-this, even though it's semantically broken in many ways, and in many cases
-doesn't actually do what people think it does. cgroupsv2 is where things are
-going, and most new kernel features in this area are only added to cgroupsv2,
-and not cgroupsv1 anymore. For example cgroupsv2 provides proper cgroup-empty
-notifications, has support for all kinds of per-cgroup BPF magic, supports
-secure delegation of cgroup trees to less privileged processes and so on, which
-all are not available on cgroupsv1.
+Note that cgroupsv1 is currently the most deployed implementation, even though
+it's semantically broken in many ways, and in many cases doesn't actually do
+what people think it does. cgroupsv2 is where things are going, and most new
+kernel features in this area are only added to cgroupsv2, and not cgroupsv1
+anymore. For example cgroupsv2 provides proper cgroup-empty notifications, has
+support for all kinds of per-cgroup BPF magic, supports secure delegation of
+cgroup trees to less privileged processes and so on, which all are not
+available on cgroupsv1.
## Three Different Tree Setups 🌳
@@ -108,11 +108,11 @@ sync (at least mostly: sub-trees might be suppressed in certain hierarchies if
no controller usage is required for them). The fact that systemd keeps these
hierarchies in sync means that the legacy and hybrid hierarchies are
conceptually very close to the unified hierarchy. In particular this allows us
-talk of one specific cgroup and actually mean the same cgroup in all available
-controller hierarchies. e.g. if we talk about the cgroup `/foo/bar/` then we
-actually mean `/sys/fs/cgroup/cpu/foo/bar/` as well as
-`/sys/fs/cgroup/memory/foo/bar/`, `/sys/fs/cgroup/pids/foo/bar/`, and so on, in
-one. Note that in cgroupsv2 the controller hierarchies aren't orthogonal, hence
+to talk of one specific cgroup and actually mean the same cgroup in all
+available controller hierarchies. E.g. if we talk about the cgroup `/foo/bar/`
+then we actually mean `/sys/fs/cgroup/cpu/foo/bar/` as well as
+`/sys/fs/cgroup/memory/foo/bar/`, `/sys/fs/cgroup/pids/foo/bar/`, and so on.
+Note that in cgroupsv2 the controller hierarchies aren't orthogonal, hence
thinking about them as orthogonal won't help you in the long run anyway.
If you wonder how to detect which of these three modes is currently used, use
@@ -190,15 +190,14 @@ clear which manager manages which part of the tree each one can do within its
sub-graph of the tree whatever it wants.
Only sub-trees can be delegated (though whoever decides to request a sub-tree
-can delegate sub-sub-trees further to somebody else if they like
-it). Delegation takes place at a specific cgroup: in systemd there's a
-`Delegate=` property you can set for a service or scope unit. If you do, it's
-the cut-off point for systemd's cgroup management: the unit itself is managed
-by systemd, i.e. all its attributes are managed exclusively by systemd, however
-your program may create/remove sub-cgroups inside it freely, and those then
-become exclusive property of your program, systemd won't touch them — all
-attributes of *those* sub-cgroups can be manipulated freely and exclusively by
-your program.
+can delegate sub-sub-trees further to somebody else if they like). Delegation
+takes place at a specific cgroup: in systemd there's a `Delegate=` property you
+can set for a service or scope unit. If you do, it's the cut-off point for
+systemd's cgroup management: the unit itself is managed by systemd, i.e. all
+its attributes are managed exclusively by systemd, however your program may
+create/remove sub-cgroups inside it freely, and those then become exclusive
+property of your program, systemd won't touch them — all attributes of *those*
+sub-cgroups can be manipulated freely and exclusively by your program.
By turning on the `Delegate=` property for a scope or service you get a few
guarantees:
@@ -231,11 +230,11 @@ the current kernel or was turned off) or more. If no list is specified
delegated.
Let's stress one thing: delegation is available on scope and service units
-only. It's expressly not available on slice units. Why that? Because slice
-units are our *inner* nodes of the cgroup trees and we freely attach service
-and scopes to them. If we'd allow delegation on slice units then this would
-mean that that both systemd and your own manager would create/delete cgroups
-below the slice unit and that conflicts with the single-writer rule.
+only. It's expressly not available on slice units. Why? Because slice units are
+our *inner* nodes of the cgroup trees and we freely attach service and scopes
+to them. If we'd allow delegation on slice units then this would mean that
+both systemd and your own manager would create/delete cgroups below the slice
+unit and that conflicts with the single-writer rule.
So, if you want to do your own raw cgroups kernel level access, then allocate a
scope unit, or a service unit (or just use the service unit you already have
@@ -248,18 +247,19 @@ cgroups for it, as you want your manager to be able to run on systemd systems.
You basically have three options:
-1. 😊 The *integration-is-good* option. For this, you register each container you
- have either as systemd service (i.e. let systemd invoke the executor binary
- for you) or systemd scope (i.e. your manager executes the binary directly,
- but then tells systemd about it. In this mode the administrator can use the
- usual systemd resource management commands individually on containers. By
- turning on `Delegate=` for these scopes or services you make it possible to
- run cgroup-enabled programs in your containers, for example a systemd
- instance running inside it. This option has two sub-options:
+1. 😊 The *integration-is-good* option. For this, you register each container
+ you have either as a systemd service (i.e. let systemd invoke the executor
+ binary for you) or a systemd scope (i.e. your manager executes the binary
+ directly, but then tells systemd about it. In this mode the administrator
+ can use the usual systemd resource management and reporting commands
+ individually on those containers. By turning on `Delegate=` for these scopes
+ or services you make it possible to run cgroup-enabled programs in your
+ containers, for example a nested systemd instance. This option has two
+ sub-options:
- a. You register the service or scope transiently directly by contacting
- systemd via D-Bus. In this case systemd will just manage the unit for you and
- nothing else.
+ a. You transiently register the service or scope by directly contacting
+ systemd via D-Bus. In this case systemd will just manage the unit for you
+ and nothing else.
b. Instead you register the service or scope through `systemd-machined`
(also via D-Bus). This mini-daemon is basically just a proxy for the same
@@ -308,9 +308,9 @@ are:
* on cgroupsv1: `cpu`, `cpuacct`, `blkio`, `memory`, `devices`, `pids`
* on cgroupsv2: `cpu`, `io`, `memory`, `pids`
-It is our intention to natively support all cgroupsv2 controllers that might
-come up sooner or later. However, regarding cgroupsv1: at this point we will
-not add support for any other controllers anymore. This means systemd currently
+It is our intention to natively support all cgroupsv2 controllers as they are
+added to the kernel. However, regarding cgroupsv1: at this point we will not
+add support for any other controllers anymore. This means systemd currently
does not and will never manage the following controllers on cgroupsv1:
`freezer`, `cpuset`, `net_cls`, `perf_event`, `net_prio`, `hugetlb`. Why not?
Depending on the case, either their API semantics or implementations aren't
@@ -359,7 +359,7 @@ optional (but of course wise).
Note one particular asymmetry here though: systemd will try to take possession
of the root cgroup you pass to it *in* *full*, i.e. it will not only
-create/remove child cgroups below it it will also attempt to manage the
+create/remove child cgroups below it, it will also attempt to manage the
attributes of it. OTOH as mentioned above, when delegating a cgroup tree to
somebody else it only passes the rights to create/remove sub-cgroups, but will
insist on managing the delegated cgroup tree's top-level attributes. Or in
@@ -424,17 +424,28 @@ unified you (of course, I guess) need to provide only `/sys/fs/cgroup/` itself.
cgroup tree of systemd itself is out of limits for you. It's fine to *read*
from any attribute you like however. That's totally OK and welcome.
-4. 🚫 When not using `CLONE_NEWCGROUP` when delegating a sub-tree to a container
- payload running systemd, then don't get the idea that you can bind mount
- only a sub-tree of the host's cgroup tree into the container. Part of the
- cgroup API is that `/proc/$PID/cgroup` reports the cgroup path of every
+4. 🚫 When not using `CLONE_NEWCGROUP` when delegating a sub-tree to a
+ container payload running systemd, then don't get the idea that you can bind
+ mount only a sub-tree of the host's cgroup tree into the container. Part of
+ the cgroup API is that `/proc/$PID/cgroup` reports the cgroup path of every
process, and hence any path below `/sys/fs/cgroup/` needs to match what
`/proc/$PID/cgroup` of the payload processes reports. What you can do safely
- however, is mount the upper parts of the cgroup tree read-only or even
- replace it with an intermediary `tmpfs`, as long as the path to the
- delegated sub-tree remains accessible as-is.
-
-5. ⚡ Think twice before delegating cgroupsv1 controllers to less privileged
+ however, is mount the upper parts of the cgroup tree read-only (or even
+ replace the middle bits with an intermediary `tmpfs` — but be careful not to
+ break the `statfs()` detection logic discussed above), as long as the path
+ to the delegated sub-tree remains accessible as-is.
+
+5. ⚡ Currently, the algorithm for mapping between slice/scope/service unit
+ naming and their cgroup paths is not considered public API of systemd, and
+ may change in future versions. This means: it's best to avoid implementing a
+ local logic of translating cgroup paths to slice/scope/service names in your
+ program, or vice versa — it's likely going to break sooner or later. Use the
+ appropriate D-Bus API calls for that instead, so that systemd translates
+ this for you. (Specifically: each Unit object has a `ControlGroup` property
+ to get the cgroup for a unit. The method `GetUnitByControlGroup()` may be
+ used to get the unit for a cgroup.)
+
+6. ⚡ Think twice before delegating cgroupsv1 controllers to less privileged
containers. It's not safe, you basically allow your containers to freeze the
system with that and worse. Delegation is a strongpoint of cgroupsv2 though,
and there it's safe to treat delegation boundaries as privilege boundaries.
diff --git a/doc/CODE_QUALITY.md b/doc/CODE_QUALITY.md
new file mode 100644
index 0000000000..d020b19c07
--- /dev/null
+++ b/doc/CODE_QUALITY.md
@@ -0,0 +1,60 @@
+# Code Quality Tools
+
+The systemd project has a number of code quality tools set up in the source
+tree and on the github infrastructure. Here's an incomprehensive list of the
+available functionality:
+
+1. Use `ninja -C build test` to run the unit tests. Some tests are skipped if
+ no privileges are available, hence consider also running them with `sudo
+ ninja -C build test`. A couple of unit tests are considered "unsafe" (as
+ they change system state); to run those too, build with `meson
+ -Dtests=unsafe`. Finally, some unit tests are considered to be very slow,
+ build them too with `meson -Dslow-tests=true`. (Note that there are a couple
+ of manual tests in addition to these unit tests.)
+
+2. Use `./test/run-integration-tests.sh` to run the full integration test
+ suite. This will build OS images with a number of integration tests and run
+ them in nspawn and qemu. Requires root.
+
+3. Use `./coccinelle/run-coccinelle.sh` to run all
+ [Coccinelle](http://coccinelle.lip6.fr/) semantic patch scripts we ship. The
+ output will show false positives, hence take it with a pinch of salt.
+
+4. Use `./tools/find-double-newline.sh recdiff` to find double newlines. Use
+ `./tools/find-double-newline.sh recpatch` to fix them. Take this with a grain
+ of salt, in particular as we generally leave foreign header files we include in
+ our tree unmodified, if possible.
+
+5. Similar use `./tools/find-tabs.sh recdiff` to find TABs, and
+ `./tools/find-tabs.sh recpatch` to fix them. (Again, grain of salt, foreign
+ headers should usually be left unmodified.)
+
+6. Use `ninja -C build check-api-docs` to compare the list of exported
+ symbols of `libsystemd.so` and `libudev.so` with the list of man pages. Symbols
+ lacking documentation are highlighted.
+
+7. Use `ninja -C build hwdb-update` to automatically download and import the
+ PCI, USB and OUI databases into hwdb.
+
+8. Use `ninja -C build man/update-man-rules` to update the meson rules for
+ building man pages automatically from the docbook XML files included in
+ `man/`.
+
+9. There are multiple CI systems in use that run on every github PR submission.
+
+10. [Coverity](https://scan.coverity.com/) is analyzing systemd master in
+ regular intervals. The reports are available
+ [online](https://scan.coverity.com/projects/systemd).
+
+11. [oss-fuzz](https://oss-fuzz.com/) is continuously fuzzing the
+ codebase. Reports are available
+ [online](https://oss-fuzz.com/v2/testcases?project=systemd).
+
+12. Our tree includes `.editorconfig`, `.dir-locals.el` and `.vimrc` files, to
+ ensure that editors follow the right indentiation styles automatically.
+
+13. When building systemd from a git checkout the build scripts will
+ automatically enable a git commit hook that ensures whitespace cleanliness.
+
+Access to Coverity and oss-fuzz reports is limited. Please reach out the the
+maintainers is you need access.
diff --git a/doc/CODING_STYLE b/doc/CODING_STYLE
index ae818126cb..26928d2e2d 100644
--- a/doc/CODING_STYLE
+++ b/doc/CODING_STYLE
@@ -7,9 +7,11 @@
comments easily discernable from explanatory, documenting code comments
(i.e. committable stuff).
-- Don't break code lines too eagerly. We do *not* force line breaks at
- 80ch, all of today's screens should be much larger than that. But
- then again, don't overdo it, ~119ch should be enough really.
+- Don't break code lines too eagerly. We do *not* force line breaks at 80ch,
+ all of today's screens should be much larger than that. But then again, don't
+ overdo it, ~119ch should be enough really. The .editorconfig, .vimrc and
+ .dir-locals.el files contained in the repository will set this limit up for
+ you automatically, if you let them (as well as a few other things).
- Variables and functions *must* be static, unless they have a
prototype, and are supposed to be exported.
@@ -67,7 +69,7 @@
values. Do not mix usec and msec, and usec and whatnot.
- Make use of _cleanup_free_ and friends. It makes your code much
- nicer to read!
+ nicer to read (and shorter)!
- Be exceptionally careful when formatting and parsing floating point
numbers. Their syntax is locale dependent (i.e. "5.000" in en_US is
@@ -99,21 +101,15 @@
- Do not write "foo ()", write "foo()".
-- Please use streq() and strneq() instead of strcmp(), strncmp() where applicable.
+- Please use streq() and strneq() instead of strcmp(), strncmp() where
+ applicable (i.e. wherever you just care about equality/inequality, not about
+ the sorting order).
-- Please do not allocate variables on the stack in the middle of code,
- even if C99 allows it. Wrong:
+- Preferably allocate stack variables on the top of the block:
{
- a = 5;
- int b;
- b = a;
- }
+ int a, b;
- Right:
-
- {
- int b;
a = 5;
b = a;
}
@@ -344,7 +340,7 @@
- Avoid leaving long-running child processes around, i.e. fork()s that
are not followed quickly by an execv() in the child. Resource
management is unclear in this case, and memory CoW will result in
- unexpected penalties in the parent much much later on.
+ unexpected penalties in the parent much, much later on.
- Don't block execution for arbitrary amounts of time using usleep()
or a similar call, unless you really know what you do. Just "giving
@@ -440,3 +436,25 @@
string, always apply the C-style unescaping fist, followed by the specifier
expansion. When doing the reverse, make sure to escape '%' in specifier-style
first (i.e. '%' → '%%'), and then do C-style escaping where necessary.
+
+- It's a good idea to use O_NONBLOCK when opening 'foreign' regular files, i.e
+ file system objects that are supposed to be regular files whose paths where
+ specified by the user and hence might actually refer to other types of file
+ system objects. This is a good idea so that we don't end up blocking on
+ 'strange' file nodes, for example if the user pointed us to a FIFO or device
+ node which may block when opening. Moreover even for actual regular files
+ O_NONBLOCK has a benefit: it bypasses any mandatory lock that might be in
+ effect on the regular file. If in doubt consider turning off O_NONBLOCK again
+ after opening.
+
+- When referring to a configuration file option in the documentation and such,
+ please always suffix it with "=", to indicate that it is a configuration file
+ setting.
+
+- When referring to a command line option in the documentation and such, please
+ always prefix with "--" or "-" (as appropriate), to indicate that it is a
+ command line option.
+
+- When referring to a file system path that is a directory, please always
+ suffix it with "/", to indicate that it is a directory, not a regular file
+ (or other file system object).
diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md
index 581bf3c238..85d26fe28c 100644
--- a/doc/ENVIRONMENT.md
+++ b/doc/ENVIRONMENT.md
@@ -89,3 +89,10 @@ nss-systemd:
* `$SYSTEMD_NSS_BYPASS_BUS=1` — if set, `nss-systemd` won't use D-Bus to do
dynamic user lookups. This is primarily useful to make `nss-systemd` work
safely from within `dbus-daemon`.
+
+systemd-timedated:
+
+* `$SYSTEMD_TIMEDATED_NTP_SERVICES=…` — colon-separated list of unit names of
+ NTP client services. If set, `timedatectl set-ntp on` enables and starts the
+ first existing unit listed in the environment variable, and
+ `timedatectl set-ntp off` disables and stops all listed units.
diff --git a/doc/HACKING b/doc/HACKING
index 0682af27ba..182b0bac8c 100644
--- a/doc/HACKING
+++ b/doc/HACKING
@@ -20,6 +20,11 @@ test executable. For features at a higher level, tests in src/test/ are very
strongly recommended. If that is no possible, integration tests in test/ are
encouraged.
+Please also have a look at our list of code quality tools we have setup for systemd,
+to ensure our codebase stays in good shape:
+
+ https://github.com/systemd/systemd/blob/master/doc/CODE_QUALITY.md
+
Please always test your work before submitting a PR. For many of the components
of systemd testing is straight-forward as you can simply compile systemd and
run the relevant tool from the build directory.
@@ -68,6 +73,7 @@ for systemd (this example is for Fedora):
$ meson build # configure the build
$ ninja -C build # build it locally, see if everything compiles fine
$ ninja -C build test # run some simple regression tests
+ $ (umask 077; echo 123 > mkosi.rootpw) # set root password used by mkosi
$ sudo mkosi # build a test image
$ sudo systemd-nspawn -bi image.raw # boot up the test image
$ git add -p # interactively put together your patch
@@ -91,10 +97,10 @@ function and add it to the list in src/fuzz/meson.build.
Whenever possible, a seed corpus and a dictionary should also be added with new
fuzz targets. The dictionary should be named src/fuzz/fuzz-foo.dict and the seed
corpus should be built and exported as $OUT/fuzz-foo_seed_corpus.zip in
-scripts/oss-fuzz.sh.
+tools/oss-fuzz.sh.
The fuzzers can be built locally if you have libFuzzer installed by running
-scripts/oss-fuzz.sh. You should also confirm that the fuzzer runs in the
+tools/oss-fuzz.sh. You should also confirm that the fuzzer runs in the
OSS-Fuzz environment by checking out the OSS-Fuzz repo, and then running
commands like this:
diff --git a/doc/PORTABLE_SERVICES.md b/doc/PORTABLE_SERVICES.md
new file mode 100644
index 0000000000..1833244447
--- /dev/null
+++ b/doc/PORTABLE_SERVICES.md
@@ -0,0 +1,251 @@
+# Portable Services Introduction
+
+This systemd version includes a preview of the "portable service"
+concept. "Portable Services" are supposed to be an incremental improvement over
+traditional system services, making two specific facets of container management
+available to system services more readily. Specifically:
+
+1. The bundling of applications, i.e. packing up multiple services, their
+ binaries and all their dependencies in a single image, and running them
+ directly from it.
+
+2. Stricter default security policies, i.e. sand-boxing of applications.
+
+The primary tool for interfacing with "portable services" is the new
+"portablectl" program. It's currently shipped in /usr/lib/systemd/portablectl
+(i.e. not in the `$PATH`), since it's not yet considered part of the officially
+supported systemd interfaces — it's a preview still after all.
+
+Portable services don't bring anything inherently new to the table. All they do
+is put together known concepts in a slightly nicer way to cover a specific set
+of use-cases in a nicer way.
+
+# So, what *is* a "Portable Service"?
+
+A portable service is ultimately just an OS tree, either inside of a directory
+tree, or inside a raw disk image containing a Linux file system. This tree is
+called the "image". It can be "attached" or "detached" from the system. When
+"attached" specific systemd units from the image are made available on the host
+system, then behaving pretty much exactly like locally installed system
+services. When "detached" these units are removed again from the host, leaving
+no artifacts around (except maybe messages they might have logged).
+
+The OS tree/image can be created with any tool of your choice. For example, you
+can use `dnf --installroot=` if you like, or `debootstrap`, the image format is
+entirely generic, and doesn't have to carry any specific metadata beyond what
+distribution images carry anyway. Or to say this differently: the image format
+doesn't define any new metadata as unit files and OS tree directories or disk
+images are already sufficient, and pretty universally available these days. One
+particularly nice tool for creating suitable images is
+[mkosi](https://github.com/systemd/mkosi), but many other existing tools will
+do too.
+
+If you so will, "Portable Services" are a nicer way to manage chroot()
+environments, with better security, tooling and behavior.
+
+# Where's the difference to a "Container"?
+
+"Container" is a very vague term, after all it is used for
+systemd-nspawn/LXC-type OS containers, for Docker/rkt-like micro service
+containers, and even certain 'lightweight' VM runtimes.
+
+The "portable service" concept ultimately will not provide a fully isolated
+environment to the payload, like containers mostly intend to. Instead they are
+from the beginning more alike regular system services, can be controlled with
+the same tools, are exposed the same way in all infrastructure and so on. Their
+main difference is that the use a different root directory than the rest of the
+system. Hence, the intention is not to run code in a different, isolated world
+from the host — like most containers would do it —, but to run it in the same
+world, but with stricter access controls on what the service can see and do.
+
+As one point of differentiation: as programs run as "portable services" are
+pretty much regular system services, they won't run as PID 1 (like Docker would
+do it), but as normal process. A corollary of that is that they aren't supposed
+to manage anything in their own environment (such as the network) as the
+execution environment is mostly shared with the rest of the system.
+
+The primary focus use-case of "portable services" is to extend the host system
+with encapsulated extensions, but provide almost full integration with the rest
+of the system, though possibly restricted by effective security knobs. This
+focus includes system extensions otherwise sometimes called "super-privileged
+containers".
+
+Note that portable services are only available for system services, not for
+user services. i.e. the functionality cannot be used for the stuff
+bubblewrap/flatpak is focusing on.
+
+# Mode of Operation
+
+If you have portable service image, maybe in a raw disk image called
+`foobar_0.7.23.raw`, then attaching the services to the host is as easy as:
+
+```
+# /usr/lib/systemd/portablectl attach foobar_0.7.23.raw
+```
+
+This command does the following:
+
+1. It dissects the image, checks and validates the `/etc/os-release` data of
+ the image, and looks for all included unit files.
+
+2. It copies out all unit files with a suffix of `.service`, `.socket`,
+ `.target`, `.timer` and `.path`. whose name begins with the image's name
+ (with the .raw removed), truncated at the first underscore (if there is
+ one). This prefix name generated from the image name must be followed by a
+ ".", "-" or "@" character in the unit name. Or in other words, given the
+ image name of `foobar_0.7.23.raw` all unit files matching
+ `foobar-*.{service|socket|target|timer|path}`,
+ `foobar@.{service|socket|target|timer|path}` as well as
+ `foobar.*.{service|socket|target|timer|path}` and
+ `foobar.{service|socket|target|timer|path}` are copied out. These unit files
+ are placed in `/etc/systemd/system/` like regular unit files. Within the
+ images the unit files are looked for at the usual locations, i.e. in
+ `/usr/lib/systemd/system/` and `/etc/systemd/system/` and so on, relative to
+ the image's root.
+
+3. For each such unit file a drop-in file is created. Let's say
+ `foobar-waldo.service` was one of the unit files copied to
+ `/etc/systemd/system/`, then a drop-in file
+ `/etc/systemd/system/foobar-waldo.service.d/20-portable.conf` is created,
+ containing a few lines of additional configuration:
+
+ ```
+ [Service]
+ RootImage=/path/to/foobar.raw
+ Environment=PORTABLE=foobar
+ LogExtraFields=PORTABLE=foobar
+ ```
+
+4. For each such unit a "profile" drop-in is linked in. This "profile" drop-in
+ generally contains security options that lock down the service. By default
+ the `default` profile is used, which provides a medium level of
+ security. There's also `trusted` which runs the service at the highest
+ privileges, i.e. host's root and everything. The `strict` profile comes with
+ the toughest security restrictions. Finally, `nonetwork` is like `default`
+ but without network access. Users may define their own profiles too (or
+ modify the existing ones)
+
+And that's already it.
+
+Note that the images need to stay around (and the same location) as long as the
+portable service is attached. If an image is moved, the `RootImage=` line
+written to the unit drop-in would point to an non-existing place, and break the
+logic.
+
+The `portablectl detach` command executes the reverse operation: it looks for
+the drop-ins and the unit files associated with the image, and removes them
+again.
+
+Note that `portable attach` won't enable or start any of the units it copies
+out. This still has to take place in a second, separate step. (That said We
+might add options to do this automatically later on.).
+
+# Requirements on Images
+
+Note that portable services don't introduce any new image format, but most OS
+images should just work the way they are. Specifically, the following
+requirements are made for an image that can be attached/detached with
+`portablectl`.
+
+1. It must contain a binary (and its dependencies) that shall be invoked,
+ including all its dependencies. If binary code, the code needs to be
+ compiled for an architecture compatible with the host.
+
+2. The image must either be a plain sub-directory (or btrfs subvolume)
+ containing the binaries and its dependencies in a classic Linux OS tree, or
+ must be a raw disk image either containing only one, naked file system, or
+ an image with a partition table understood by the Linux kernel with only a
+ single partition defined, or alternatively, a GPT partition table with a set
+ of properly marked partitions following the [Discoverable Partitions
+ Specification](https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/).
+
+3. The image must at least contain one matching unit file, with the right name
+ prefix and suffix (see above). The unit file is searched in the usual paths,
+ i.e. primarily /etc/systemd/system/ and /usr/lib/systemd/system/ within the
+ image. (The implementation will check a couple of other paths too, but it's
+ recommended to use these two paths.)
+
+4. The image must contain an os-release file, either in /etc/os-release or
+ /usr/lib/os-release. The file should follow the standard format.
+
+Note that generally images created by tools such as `debootstrap`, `dnf
+--installroot=` or `mkosi` qualify for all of the above in one way or
+another. If you wonder what the most minimal image would be that complies with
+the requirements above, it could consist of this:
+
+```
+/usr/bin/minimald # a statically compiled binary
+/usr/lib/systemd/minimal-test.service # the unit file for the service, with ExecStart=/usr/bin/minimald
+/usr/lib/os-release # an os-release file explaining what this is
+```
+
+And that's it.
+
+Note that qualifying images do not have to contain an init system of their
+own. If they do, it's fine, it will be ignored by the portable service logic,
+but they generally don't have to, and it might make sense to avoid any, to keep
+images minimal.
+
+Note that as no new image format or metadata is defined, it's very
+straight-forward to define images than can be made use of it a number of
+different ways. For example, by using `mkosi -b` you can trivially build a
+single, unified image that:
+
+1. Can be attached as portable service, to run any container services natively
+ on the host.
+
+2. Can be run as OS container, using `systemd-nspawn`, by booting the image
+ with `systemd-nspawn -i -b`.
+
+3. Can be booted directly as VM image, using a generic VM executor such as
+ `virtualbox`/`qemu`/`kvm`
+
+4. Can be booted directly on bare-metal systems.
+
+Of course, to facilitate 2, 3 and 4 you need to include an init system in the
+image. To facility 3 and 4 you also need to include a boot loader in the
+image. As mentioned `mkosi -b` takes care of all of that for you, but any other
+image generator should work too.
+
+# Execution Environment
+
+Note that the code in portable service images is run exactly like regular
+services. Hence there's no new execution environment to consider. Oh, unlike
+Docker would do it, as these are regular system services they aren't run as PID
+1 either, but with regular PID values.
+
+# Access to host resources
+
+If services shipped with this mechanism shall be able to access host resources
+(such as files or AF_UNIX sockets for IPC), use the normal `BindPaths=` and
+`BindReadOnlyPaths=` settings in unit files to mount them in. In fact the
+`default` profile mentioned above makes use of this to ensure
+`/etc/resolv.conf`, the D-Bus system bus socket or write access to the logging
+subsystem are available to the service.
+
+# Instantiation
+
+Sometimes it makes sense to instantiate the same set of services multiple
+times. The portable service concept does not introduce a new logic for this. It
+is recommended to use the regular unit templating of systemd for this, i.e. to
+include template units such as `foobar@.service`, so that instantiation is as
+simple as:
+
+```
+# /usr/lib/systemd/portablectl attach foobar_0.7.23.raw
+# systemctl enable --now foobar@instancea.service
+# systemctl enable --now foobar@instanceb.service
+…
+```
+
+The benefit of this approach is that templating works exactly the same for
+units shipped with the OS itself as for attached portable services.
+
+# Immutable images with local data
+
+It's a good idea to keep portable service images read-only during normal
+operation. In fact all but the `trusted` profile will default to this kind of
+behaviour, by setting the `ProtectSystem=strict` option. In this case writable
+service data may be placed on the host file system. Use `StateDirectory=` in
+the unit files to enable such behaviour and add a local data directory to the
+services copied onto the host.
diff --git a/doc/UIDS-GIDS.md b/doc/UIDS-GIDS.md
index c380bbe140..7755491319 100644
--- a/doc/UIDS-GIDS.md
+++ b/doc/UIDS-GIDS.md
@@ -189,7 +189,7 @@ supported for the whole system, back in the days.
assign has the lower 16bits all set to zero. That way, the upper 16bits become
a container ID of some kind, while the lower 16bits directly encode the
internal container UID. This is the way `systemd-nspawn` allocates UID ranges
-(see above). Following this allocation logic ensures best compability with
+(see above). Following this allocation logic ensures best compatibility with
`systemd-nspawn` and all other container managers following the scheme, as it
is sufficient then to check NSS for the first UID you pick regarding conflicts,
as that's what they do, too. Moreover, it makes `chown()`ing container file
diff --git a/docs/sysvinit/README.in b/doc/sysvinit/README.in
index de5d80d902..de5d80d902 100644
--- a/docs/sysvinit/README.in
+++ b/doc/sysvinit/README.in
diff --git a/doc/sysvinit/meson.build b/doc/sysvinit/meson.build
new file mode 100644
index 0000000000..fbac59ae49
--- /dev/null
+++ b/doc/sysvinit/meson.build
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+file = configure_file(
+ input : 'README.in',
+ output : 'README',
+ configuration : substs)
+
+if conf.get('HAVE_SYSV_COMPAT') == 1
+ install_data(file,
+ install_dir : sysvinit_path)
+endif
diff --git a/docs/var-log/README.in b/doc/var-log/README.in
index 2e64fb196a..2e64fb196a 100644
--- a/docs/var-log/README.in
+++ b/doc/var-log/README.in
diff --git a/doc/var-log/meson.build b/doc/var-log/meson.build
new file mode 100644
index 0000000000..0ddff20ce5
--- /dev/null
+++ b/doc/var-log/meson.build
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+file = configure_file(
+ input : 'README.in',
+ output : 'README',
+ configuration : substs)
+
+if conf.get('HAVE_SYSV_COMPAT') == 1
+ install_data(file,
+ install_dir : varlogdir)
+endif
diff --git a/docs/sysvinit/meson.build b/docs/sysvinit/meson.build
deleted file mode 100644
index 5c1aa4cc20..0000000000
--- a/docs/sysvinit/meson.build
+++ /dev/null
@@ -1,26 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
-file = configure_file(
- input : 'README.in',
- output : 'README',
- configuration : substs)
-
-if conf.get('HAVE_SYSV_COMPAT') == 1
- install_data(file,
- install_dir : sysvinit_path)
-endif
diff --git a/docs/var-log/meson.build b/docs/var-log/meson.build
deleted file mode 100644
index fc14c0405e..0000000000
--- a/docs/var-log/meson.build
+++ /dev/null
@@ -1,26 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
-file = configure_file(
- input : 'README.in',
- output : 'README',
- configuration : substs)
-
-if conf.get('HAVE_SYSV_COMPAT') == 1
- install_data(file,
- install_dir : varlogdir)
-endif
diff --git a/hwdb/20-OUI.hwdb b/hwdb/20-OUI.hwdb
index 4bd1e1e07f..1f24cd6016 100644
--- a/hwdb/20-OUI.hwdb
+++ b/hwdb/20-OUI.hwdb
@@ -591,7 +591,7 @@ OUI:0000C2*
ID_OUI_FROM_DATABASE=INFORMATION PRESENTATION TECH.
OUI:0000C3*
- ID_OUI_FROM_DATABASE=HARRIS CORP COMPUTER SYS DIV
+ ID_OUI_FROM_DATABASE=Harris Corporation
OUI:0000C4*
ID_OUI_FROM_DATABASE=WATERS DIV. OF MILLIPORE
@@ -780,10 +780,10 @@ OUI:000101*
ID_OUI_FROM_DATABASE=Private
OUI:000102*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:000103*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:000104*
ID_OUI_FROM_DATABASE=DVICO Co., Ltd.
@@ -873,7 +873,7 @@ OUI:000120*
ID_OUI_FROM_DATABASE=OSCILLOQUARTZ S.A.
OUI:000121*
- ID_OUI_FROM_DATABASE=Watchguard Technologies, Inc.
+ ID_OUI_FROM_DATABASE=WatchGuard Technologies, Inc.
OUI:000122*
ID_OUI_FROM_DATABASE=Trend Communications, Ltd.
@@ -993,7 +993,7 @@ OUI:000148*
ID_OUI_FROM_DATABASE=X-traWeb Inc.
OUI:000149*
- ID_OUI_FROM_DATABASE=T.D.T. Transfer Data Test GmbH
+ ID_OUI_FROM_DATABASE=TDT AG
OUI:00014A*
ID_OUI_FROM_DATABASE=Sony Corporation
@@ -1731,7 +1731,7 @@ OUI:00023E*
ID_OUI_FROM_DATABASE=Selta Telematica S.p.a
OUI:00023F*
- ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC.
+ ID_OUI_FROM_DATABASE=Compal Electronics INC.
OUI:000240*
ID_OUI_FROM_DATABASE=Seedek Co., Ltd.
@@ -3111,7 +3111,7 @@ OUI:00040A*
ID_OUI_FROM_DATABASE=Sage Systems
OUI:00040B*
- ID_OUI_FROM_DATABASE=3COM EUROPE LTD.
+ ID_OUI_FROM_DATABASE=3COM EUROPE LTD
OUI:00040C*
ID_OUI_FROM_DATABASE=Kanno Works, Ltd.
@@ -3429,10 +3429,10 @@ OUI:000474*
ID_OUI_FROM_DATABASE=LEGRAND
OUI:000475*
- ID_OUI_FROM_DATABASE=3 Com Corporation
+ ID_OUI_FROM_DATABASE=3COM
OUI:000476*
- ID_OUI_FROM_DATABASE=3 Com Corporation
+ ID_OUI_FROM_DATABASE=3COM
OUI:000477*
ID_OUI_FROM_DATABASE=Scalant Systems, Inc.
@@ -3924,7 +3924,7 @@ OUI:000519*
ID_OUI_FROM_DATABASE=Siemens Building Technologies AG,
OUI:00051A*
- ID_OUI_FROM_DATABASE=3COM EUROPE LTD.
+ ID_OUI_FROM_DATABASE=3COM EUROPE LTD
OUI:00051B*
ID_OUI_FROM_DATABASE=Magic Control Technology Corporation
@@ -4818,7 +4818,7 @@ OUI:000643*
ID_OUI_FROM_DATABASE=SONO Computer Co., Ltd.
OUI:000644*
- ID_OUI_FROM_DATABASE=neix,Inc
+ ID_OUI_FROM_DATABASE=NextGen Business Solutions, Inc
OUI:000645*
ID_OUI_FROM_DATABASE=Meisei Electric Co. Ltd.
@@ -5034,7 +5034,7 @@ OUI:00068B*
ID_OUI_FROM_DATABASE=AirRunner Technologies, Inc.
OUI:00068C*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:00068D*
ID_OUI_FROM_DATABASE=SEPATON, Inc.
@@ -5556,7 +5556,7 @@ OUI:000739*
ID_OUI_FROM_DATABASE=Scotty Group Austria Gmbh
OUI:00073A*
- ID_OUI_FROM_DATABASE=Inventel Systemes
+ ID_OUI_FROM_DATABASE=INVENTEL
OUI:00073B*
ID_OUI_FROM_DATABASE=Tenovis GmbH & Co KG
@@ -7884,7 +7884,7 @@ OUI:000A5D*
ID_OUI_FROM_DATABASE=FingerTec Worldwide Sdn Bhd
OUI:000A5E*
- ID_OUI_FROM_DATABASE=3COM Corporation
+ ID_OUI_FROM_DATABASE=3COM
OUI:000A5F*
ID_OUI_FROM_DATABASE=almedio inc.
@@ -8253,7 +8253,7 @@ OUI:000AD8*
ID_OUI_FROM_DATABASE=IPCserv Technology Corp.
OUI:000AD9*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:000ADA*
ID_OUI_FROM_DATABASE=Vindicator Technologies
@@ -8475,7 +8475,7 @@ OUI:000B22*
ID_OUI_FROM_DATABASE=Environmental Systems and Services
OUI:000B23*
- ID_OUI_FROM_DATABASE=Siemens Subscriber Networks
+ ID_OUI_FROM_DATABASE=Siemens Home & Office Comm. Devices
OUI:000B24*
ID_OUI_FROM_DATABASE=AirLogic
@@ -8859,7 +8859,7 @@ OUI:000BA2*
ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd
OUI:000BA3*
- ID_OUI_FROM_DATABASE=Siemens AG, I&S
+ ID_OUI_FROM_DATABASE=Siemens AG
OUI:000BA4*
ID_OUI_FROM_DATABASE=Shiron Satellite Communications Ltd. (1996)
@@ -10695,7 +10695,7 @@ OUI:000E06*
ID_OUI_FROM_DATABASE=Team Simoco Ltd
OUI:000E07*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:000E08*
ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
@@ -11505,7 +11505,7 @@ OUI:000F14*
ID_OUI_FROM_DATABASE=Mindray Co., Ltd.
OUI:000F15*
- ID_OUI_FROM_DATABASE=Kjaerulff1 A/S
+ ID_OUI_FROM_DATABASE=Icotera A/S
OUI:000F16*
ID_OUI_FROM_DATABASE=JAY HOW TECHNOLOGY CO.,
@@ -11970,7 +11970,7 @@ OUI:000FAF*
ID_OUI_FROM_DATABASE=Dialog Inc.
OUI:000FB0*
- ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC.
+ ID_OUI_FROM_DATABASE=Compal Electronics INC.
OUI:000FB1*
ID_OUI_FROM_DATABASE=Cognio Inc.
@@ -12108,7 +12108,7 @@ OUI:000FDD*
ID_OUI_FROM_DATABASE=SORDIN AB
OUI:000FDE*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:000FDF*
ID_OUI_FROM_DATABASE=SOLOMON Technology Corp.
@@ -12435,7 +12435,7 @@ OUI:00104A*
ID_OUI_FROM_DATABASE=The Parvus Corporation
OUI:00104B*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:00104C*
ID_OUI_FROM_DATABASE=Teledyne LeCroy, Inc
@@ -12480,7 +12480,7 @@ OUI:001059*
ID_OUI_FROM_DATABASE=DIABLO RESEARCH CO. LLC
OUI:00105A*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:00105B*
ID_OUI_FROM_DATABASE=NET INSIGHT AB
@@ -13131,7 +13131,7 @@ OUI:001132*
ID_OUI_FROM_DATABASE=Synology Incorporated
OUI:001133*
- ID_OUI_FROM_DATABASE=Siemens Austria SIMEA
+ ID_OUI_FROM_DATABASE=Siemens AG Austria
OUI:001134*
ID_OUI_FROM_DATABASE=MediaCell, Inc.
@@ -13983,7 +13983,7 @@ OUI:00124E*
ID_OUI_FROM_DATABASE=XAC AUTOMATION CORP.
OUI:00124F*
- ID_OUI_FROM_DATABASE=Pentair Thermal Management
+ ID_OUI_FROM_DATABASE=nVent
OUI:001250*
ID_OUI_FROM_DATABASE=Tokyo Aircaft Instrument Co., Ltd.
@@ -14241,7 +14241,7 @@ OUI:0012A4*
ID_OUI_FROM_DATABASE=ThingMagic, LLC
OUI:0012A5*
- ID_OUI_FROM_DATABASE=Stargen, Inc.
+ ID_OUI_FROM_DATABASE=Dolphin Interconnect Solutions AS
OUI:0012A6*
ID_OUI_FROM_DATABASE=Dolby Australia
@@ -14460,7 +14460,7 @@ OUI:0012ED*
ID_OUI_FROM_DATABASE=AVG Advanced Technologies
OUI:0012EE*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:0012EF*
ID_OUI_FROM_DATABASE=OneAccess SA
@@ -15003,7 +15003,7 @@ OUI:0013A2*
ID_OUI_FROM_DATABASE=MaxStream, Inc
OUI:0013A3*
- ID_OUI_FROM_DATABASE=Siemens Com CPE Devices
+ ID_OUI_FROM_DATABASE=Siemens Home & Office Comm. Devices
OUI:0013A4*
ID_OUI_FROM_DATABASE=KeyEye Communications
@@ -16914,7 +16914,7 @@ OUI:00161F*
ID_OUI_FROM_DATABASE=SUNWAVETEC Co., Ltd.
OUI:001620*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001621*
ID_OUI_FROM_DATABASE=Colorado Vnet
@@ -17370,7 +17370,7 @@ OUI:0016B7*
ID_OUI_FROM_DATABASE=Seoul Commtech
OUI:0016B8*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:0016B9*
ID_OUI_FROM_DATABASE=ProCurve Networking by HP
@@ -18132,7 +18132,7 @@ OUI:0017B5*
ID_OUI_FROM_DATABASE=Peerless Systems Corporation
OUI:0017B6*
- ID_OUI_FROM_DATABASE=Aquantia
+ ID_OUI_FROM_DATABASE=Aquantia Corporation
OUI:0017B7*
ID_OUI_FROM_DATABASE=Tonze Technology Co.
@@ -18315,7 +18315,7 @@ OUI:0017F2*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:0017F3*
- ID_OUI_FROM_DATABASE=Harris Corparation
+ ID_OUI_FROM_DATABASE=Harris Corporation
OUI:0017F4*
ID_OUI_FROM_DATABASE=ZERON ALLIANCE
@@ -18411,7 +18411,7 @@ OUI:001812*
ID_OUI_FROM_DATABASE=Beijing Xinwei Telecom Technology Co., Ltd.
OUI:001813*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001814*
ID_OUI_FROM_DATABASE=Mitutoyo Corporation
@@ -18573,7 +18573,7 @@ OUI:001848*
ID_OUI_FROM_DATABASE=Vecima Networks Inc.
OUI:001849*
- ID_OUI_FROM_DATABASE=Pigeon Point Systems LLC
+ ID_OUI_FROM_DATABASE=nVent, Schroff GmbH
OUI:00184A*
ID_OUI_FROM_DATABASE=Catcher, Inc.
@@ -19419,7 +19419,7 @@ OUI:001962*
ID_OUI_FROM_DATABASE=Commerciant, LP
OUI:001963*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001964*
ID_OUI_FROM_DATABASE=Doorking Inc.
@@ -20037,7 +20037,7 @@ OUI:001A30*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:001A31*
- ID_OUI_FROM_DATABASE=SCAN COIN Industries AB
+ ID_OUI_FROM_DATABASE=SCAN COIN AB
OUI:001A32*
ID_OUI_FROM_DATABASE=ACTIVA MULTIMEDIA
@@ -20241,7 +20241,7 @@ OUI:001A74*
ID_OUI_FROM_DATABASE=Procare International Co
OUI:001A75*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001A76*
ID_OUI_FROM_DATABASE=SDT information Technology Co.,LTD.
@@ -20481,7 +20481,7 @@ OUI:001AC4*
ID_OUI_FROM_DATABASE=2Wire Inc
OUI:001AC5*
- ID_OUI_FROM_DATABASE=BreakingPoint Systems, Inc.
+ ID_OUI_FROM_DATABASE=Keysight Technologies, Inc.
OUI:001AC6*
ID_OUI_FROM_DATABASE=Micro Control Designs
@@ -20925,7 +20925,7 @@ OUI:001B58*
ID_OUI_FROM_DATABASE=ACE CAD Enterprise Co., Ltd.
OUI:001B59*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001B5A*
ID_OUI_FROM_DATABASE=Apollo Imaging Technologies, Inc.
@@ -20988,7 +20988,7 @@ OUI:001B6D*
ID_OUI_FROM_DATABASE=Midtronics, Inc.
OUI:001B6E*
- ID_OUI_FROM_DATABASE=Anue Systems, Inc.
+ ID_OUI_FROM_DATABASE=Keysight Technologies, Inc.
OUI:001B6F*
ID_OUI_FROM_DATABASE=Teletrak Ltd
@@ -22518,7 +22518,7 @@ OUI:001CA3*
ID_OUI_FROM_DATABASE=Terra
OUI:001CA4*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001CA5*
ID_OUI_FROM_DATABASE=Zygo Corporation
@@ -22914,7 +22914,7 @@ OUI:001D27*
ID_OUI_FROM_DATABASE=NAC-INTERCOM
OUI:001D28*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001D29*
ID_OUI_FROM_DATABASE=Doro AB
@@ -23715,7 +23715,7 @@ OUI:001E32*
ID_OUI_FROM_DATABASE=Zensys
OUI:001E33*
- ID_OUI_FROM_DATABASE=INVENTEC Corporation
+ ID_OUI_FROM_DATABASE=INVENTEC CORPORATION
OUI:001E34*
ID_OUI_FROM_DATABASE=CryptoMetrics
@@ -23769,7 +23769,7 @@ OUI:001E44*
ID_OUI_FROM_DATABASE=SANTEC
OUI:001E45*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001E46*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -23946,7 +23946,7 @@ OUI:001E7F*
ID_OUI_FROM_DATABASE=CBM of America
OUI:001E80*
- ID_OUI_FROM_DATABASE=Last Mile Ltd.
+ ID_OUI_FROM_DATABASE=Icotera A/S
OUI:001E81*
ID_OUI_FROM_DATABASE=CNB Technology Inc.
@@ -24222,7 +24222,7 @@ OUI:001EDB*
ID_OUI_FROM_DATABASE=Giken Trastem Co., Ltd.
OUI:001EDC*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001EDD*
ID_OUI_FROM_DATABASE=WASKO S.A.
@@ -25014,7 +25014,7 @@ OUI:001FE3*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
OUI:001FE4*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:001FE5*
ID_OUI_FROM_DATABASE=In-Circuit GmbH
@@ -25281,7 +25281,7 @@ OUI:00203C*
ID_OUI_FROM_DATABASE=EUROTIME AB
OUI:00203D*
- ID_OUI_FROM_DATABASE=Honeywell ECC
+ ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls
OUI:00203E*
ID_OUI_FROM_DATABASE=LogiCan Technologies, Inc.
@@ -25623,7 +25623,7 @@ OUI:0020AE*
ID_OUI_FROM_DATABASE=ORNET DATA COMMUNICATION TECH.
OUI:0020AF*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:0020B0*
ID_OUI_FROM_DATABASE=GATEWAY DEVICES, INC.
@@ -26340,7 +26340,7 @@ OUI:00219D*
ID_OUI_FROM_DATABASE=Adesys BV
OUI:00219E*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:00219F*
ID_OUI_FROM_DATABASE=SATEL OY
@@ -27090,7 +27090,7 @@ OUI:002297*
ID_OUI_FROM_DATABASE=XMOS Semiconductor
OUI:002298*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:002299*
ID_OUI_FROM_DATABASE=SeaMicro Inc.
@@ -27609,7 +27609,7 @@ OUI:002344*
ID_OUI_FROM_DATABASE=Objective Interface Systems, Inc.
OUI:002345*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:002346*
ID_OUI_FROM_DATABASE=Vestac
@@ -28125,7 +28125,7 @@ OUI:0023F0*
ID_OUI_FROM_DATABASE=Shanghai Jinghan Weighing Apparatus Co. Ltd.
OUI:0023F1*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:0023F2*
ID_OUI_FROM_DATABASE=TVLogic
@@ -28683,7 +28683,7 @@ OUI:0024AD*
ID_OUI_FROM_DATABASE=Adolf Thies Gmbh & Co. KG
OUI:0024AE*
- ID_OUI_FROM_DATABASE=Morpho
+ ID_OUI_FROM_DATABASE=IDEMIA
OUI:0024AF*
ID_OUI_FROM_DATABASE=Dish Technologies Corp
@@ -28878,7 +28878,7 @@ OUI:0024EE*
ID_OUI_FROM_DATABASE=Wynmax Inc.
OUI:0024EF*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:0024F0*
ID_OUI_FROM_DATABASE=Seanodes
@@ -29616,7 +29616,7 @@ OUI:0025E6*
ID_OUI_FROM_DATABASE=Belgian Monitoring Systems bvba
OUI:0025E7*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:0025E8*
ID_OUI_FROM_DATABASE=Idaho Technology
@@ -29934,7 +29934,7 @@ OUI:002653*
ID_OUI_FROM_DATABASE=DaySequerra Corporation
OUI:002654*
- ID_OUI_FROM_DATABASE=3Com Corporation
+ ID_OUI_FROM_DATABASE=3COM
OUI:002655*
ID_OUI_FROM_DATABASE=Hewlett Packard
@@ -30006,7 +30006,7 @@ OUI:00266B*
ID_OUI_FROM_DATABASE=SHINE UNION ENTERPRISE LIMITED
OUI:00266C*
- ID_OUI_FROM_DATABASE=INVENTEC Corporation
+ ID_OUI_FROM_DATABASE=INVENTEC CORPORATION
OUI:00266D*
ID_OUI_FROM_DATABASE=MobileAccess Networks
@@ -30684,7 +30684,7 @@ OUI:00301D*
ID_OUI_FROM_DATABASE=SKYSTREAM, INC.
OUI:00301E*
- ID_OUI_FROM_DATABASE=3COM EUROPE LTD.
+ ID_OUI_FROM_DATABASE=3COM EUROPE LTD
OUI:00301F*
ID_OUI_FROM_DATABASE=OPTICAL NETWORKS, INC.
@@ -31842,7 +31842,7 @@ OUI:004083*
ID_OUI_FROM_DATABASE=TDA INDUSTRIA DE PRODUTOS
OUI:004084*
- ID_OUI_FROM_DATABASE=HONEYWELL ACS
+ ID_OUI_FROM_DATABASE=Honeywell International HPS
OUI:004085*
ID_OUI_FROM_DATABASE=SAAB INSTRUMENTS AB
@@ -32234,6 +32234,9 @@ OUI:0043FF*
OUI:004501*
ID_OUI_FROM_DATABASE=Versus Technology, Inc.
+OUI:00451D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:00464B*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -32259,7 +32262,7 @@ OUI:005003*
ID_OUI_FROM_DATABASE=Xrite Inc
OUI:005004*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:005006*
ID_OUI_FROM_DATABASE=TAC AB
@@ -32673,7 +32676,7 @@ OUI:005098*
ID_OUI_FROM_DATABASE=GLOBALOOP, LTD.
OUI:005099*
- ID_OUI_FROM_DATABASE=3COM EUROPE, LTD.
+ ID_OUI_FROM_DATABASE=3COM EUROPE LTD
OUI:00509A*
ID_OUI_FROM_DATABASE=TAG ELECTRONIC SYSTEMS
@@ -32865,7 +32868,7 @@ OUI:0050D9*
ID_OUI_FROM_DATABASE=ENGETRON-ENGENHARIA ELETRONICA IND. e COM. LTDA
OUI:0050DA*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:0050DB*
ID_OUI_FROM_DATABASE=CONTEMPORARY CONTROL
@@ -32966,6 +32969,9 @@ OUI:0050FE*
OUI:0050FF*
ID_OUI_FROM_DATABASE=HAKKO ELECTRONICS CO., LTD.
+OUI:0051ED*
+ ID_OUI_FROM_DATABASE=LG Innotek
+
OUI:005218*
ID_OUI_FROM_DATABASE=Wuxi Keboda Electron Co.Ltd
@@ -33032,6 +33038,9 @@ OUI:00562B*
OUI:0056CD*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:0057C1*
+ ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+
OUI:0057D2*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -33099,7 +33108,7 @@ OUI:006007*
ID_OUI_FROM_DATABASE=ACRES GAMING, INC.
OUI:006008*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:006009*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -33495,7 +33504,7 @@ OUI:00608B*
ID_OUI_FROM_DATABASE=ConferTech International
OUI:00608C*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:00608D*
ID_OUI_FROM_DATABASE=UNIPULSE CORP.
@@ -33528,7 +33537,7 @@ OUI:006096*
ID_OUI_FROM_DATABASE=T.S. MICROTECH INC.
OUI:006097*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:006098*
ID_OUI_FROM_DATABASE=HT COMMUNICATIONS
@@ -33899,6 +33908,9 @@ OUI:0071C2*
OUI:0071CC*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:007204*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. ARTIK
+
OUI:007263*
ID_OUI_FROM_DATABASE=Netcore Technology Inc.
@@ -33944,6 +33956,9 @@ OUI:007DFA*
OUI:007E56*
ID_OUI_FROM_DATABASE=China Dragon Technology Limited
+OUI:007E95*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:007F28*
ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
@@ -34755,7 +34770,7 @@ OUI:008C54*
ID_OUI_FROM_DATABASE=ADB Broadband Italia
OUI:008CFA*
- ID_OUI_FROM_DATABASE=INVENTEC Corporation
+ ID_OUI_FROM_DATABASE=INVENTEC CORPORATION
OUI:008D4E*
ID_OUI_FROM_DATABASE=CJSC NII STT
@@ -34782,7 +34797,7 @@ OUI:009003*
ID_OUI_FROM_DATABASE=APLIO
OUI:009004*
- ID_OUI_FROM_DATABASE=3COM EUROPE LTD.
+ ID_OUI_FROM_DATABASE=3COM EUROPE LTD
OUI:009005*
ID_OUI_FROM_DATABASE=PROTECH SYSTEMS CO., LTD.
@@ -35151,7 +35166,7 @@ OUI:00907E*
ID_OUI_FROM_DATABASE=VETRONIX CORP.
OUI:00907F*
- ID_OUI_FROM_DATABASE=Watchguard Technologies, Inc.
+ ID_OUI_FROM_DATABASE=WatchGuard Technologies, Inc.
OUI:009080*
ID_OUI_FROM_DATABASE=NOT LIMITED, INC.
@@ -35211,7 +35226,7 @@ OUI:009092*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:009093*
- ID_OUI_FROM_DATABASE=NANAO CORPORATION
+ ID_OUI_FROM_DATABASE=EIZO Corporation
OUI:009094*
ID_OUI_FROM_DATABASE=OSPREY TECHNOLOGIES, INC.
@@ -35388,7 +35403,7 @@ OUI:0090CD*
ID_OUI_FROM_DATABASE=ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A.
OUI:0090CE*
- ID_OUI_FROM_DATABASE=TETRA GmbH
+ ID_OUI_FROM_DATABASE=avateramedical Mechatronics GmbH
OUI:0090CF*
ID_OUI_FROM_DATABASE=NORTEL
@@ -35567,6 +35582,9 @@ OUI:009AD2*
OUI:009C02*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:009D6B*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+
OUI:009D8E*
ID_OUI_FROM_DATABASE=CARDIAC RECORDERS, INC.
@@ -35685,7 +35703,7 @@ OUI:00A023*
ID_OUI_FROM_DATABASE=APPLIED CREATIVE TECHNOLOGY, INC.
OUI:00A024*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:00A025*
ID_OUI_FROM_DATABASE=REDCOM LABS INC.
@@ -36371,6 +36389,9 @@ OUI:00A3D1*
OUI:00A509*
ID_OUI_FROM_DATABASE=WigWag Inc.
+OUI:00A5BF*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:00A6CA*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -36392,6 +36413,9 @@ OUI:00AA02*
OUI:00AA3C*
ID_OUI_FROM_DATABASE=OLIVETTI TELECOM SPA (OLTECO)
+OUI:00AA6E*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:00AA70*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
@@ -36519,7 +36543,7 @@ OUI:00B0F5*
ID_OUI_FROM_DATABASE=NetWorth Technologies, Inc.
OUI:00B338*
- ID_OUI_FROM_DATABASE=Kontron Design Manufacturing Services (M) Sdn. Bhd
+ ID_OUI_FROM_DATABASE=Kontron Asia Pacific Design Sdn. Bhd
OUI:00B342*
ID_OUI_FROM_DATABASE=MacroSAN Technologies Co., Ltd.
@@ -36530,9 +36554,15 @@ OUI:00B362*
OUI:00B56D*
ID_OUI_FROM_DATABASE=David Electronics Co., LTD.
+OUI:00B5D0*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:00B5D6*
ID_OUI_FROM_DATABASE=Omnibit Inc.
+OUI:00B670*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:00B69F*
ID_OUI_FROM_DATABASE=Latch
@@ -36554,6 +36584,9 @@ OUI:00BB01*
OUI:00BB3A*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+OUI:00BB60*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:00BB8E*
ID_OUI_FROM_DATABASE=HME Co., Ltd.
@@ -36563,6 +36596,9 @@ OUI:00BBC1*
OUI:00BBF0*
ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC.
+OUI:00BC60*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:00BD27*
ID_OUI_FROM_DATABASE=Exar Corp.
@@ -37863,7 +37899,7 @@ OUI:00D095*
ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise
OUI:00D096*
- ID_OUI_FROM_DATABASE=3COM EUROPE LTD.
+ ID_OUI_FROM_DATABASE=3COM EUROPE LTD
OUI:00D097*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -38061,7 +38097,7 @@ OUI:00D0D7*
ID_OUI_FROM_DATABASE=B2C2, INC.
OUI:00D0D8*
- ID_OUI_FROM_DATABASE=3Com Corporation
+ ID_OUI_FROM_DATABASE=3COM
OUI:00D0D9*
ID_OUI_FROM_DATABASE=DEDICATED MICROCOMPUTERS
@@ -38541,7 +38577,7 @@ OUI:00E05B*
ID_OUI_FROM_DATABASE=WEST END SYSTEMS CORP.
OUI:00E05C*
- ID_OUI_FROM_DATABASE=Panasonic Healthcare Co., Ltd.
+ ID_OUI_FROM_DATABASE=PHC Corporation
OUI:00E05D*
ID_OUI_FROM_DATABASE=UNITEC CO., LTD.
@@ -39060,7 +39096,7 @@ OUI:00E8AB*
ID_OUI_FROM_DATABASE=Meggitt Training Systems, Inc.
OUI:00EB2D*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:00EBD5*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -39147,7 +39183,7 @@ OUI:026086*
ID_OUI_FROM_DATABASE=LOGIC REPLACEMENT TECH. LTD.
OUI:02608C*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:027001*
ID_OUI_FROM_DATABASE=RACAL-DATACOM
@@ -39168,7 +39204,7 @@ OUI:02BB01*
ID_OUI_FROM_DATABASE=OCTOTHORPE CORP.
OUI:02C08C*
- ID_OUI_FROM_DATABASE=3COM CORPORATION
+ ID_OUI_FROM_DATABASE=3COM
OUI:02CF1C*
ID_OUI_FROM_DATABASE=Communication Machinery Corporation
@@ -39191,6 +39227,9 @@ OUI:0404EA*
OUI:040973*
ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+OUI:0409A5*
+ ID_OUI_FROM_DATABASE=HFR, Inc.
+
OUI:040A83*
ID_OUI_FROM_DATABASE=Alcatel-Lucent
@@ -39206,6 +39245,9 @@ OUI:040EC2*
OUI:041552*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:0415D9*
+ ID_OUI_FROM_DATABASE=Viwone
+
OUI:04180F*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -39290,6 +39332,9 @@ OUI:043A0D*
OUI:043D98*
ID_OUI_FROM_DATABASE=ChongQing QingJia Electronics CO.,LTD
+OUI:0440A9*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:044169*
ID_OUI_FROM_DATABASE=GoPro
@@ -39482,6 +39527,9 @@ OUI:047863*
OUI:047970*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:0479B7*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:047D50*
ID_OUI_FROM_DATABASE=Shenzhen Kang Ying Technology Co.Ltd.
@@ -39599,6 +39647,9 @@ OUI:04BA36*
OUI:04BBF9*
ID_OUI_FROM_DATABASE=Pavilion Data Systems Inc
+OUI:04BC87*
+ ID_OUI_FROM_DATABASE=Shenzhen JustLink Technology Co., LTD
+
OUI:04BD70*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -39632,6 +39683,51 @@ OUI:04C23E*
OUI:04C241*
ID_OUI_FROM_DATABASE=Nokia
+OUI:04C3E60*
+ ID_OUI_FROM_DATABASE=DREAMKAS LLC
+
+OUI:04C3E61*
+ ID_OUI_FROM_DATABASE=Guangdong New Pulse Electric Co., Ltd.
+
+OUI:04C3E62*
+ ID_OUI_FROM_DATABASE=SiS Technology
+
+OUI:04C3E63*
+ ID_OUI_FROM_DATABASE=Extech Electronics Co., LTD.
+
+OUI:04C3E64*
+ ID_OUI_FROM_DATABASE=Innovusion Inc.
+
+OUI:04C3E65*
+ ID_OUI_FROM_DATABASE=Invasys
+
+OUI:04C3E66*
+ ID_OUI_FROM_DATABASE=Shenzhen Shuotian Information Technology Co., LTD
+
+OUI:04C3E67*
+ ID_OUI_FROM_DATABASE=Advanced Digital Technologies, s.r.o.
+
+OUI:04C3E68*
+ ID_OUI_FROM_DATABASE=SLOC GmbH
+
+OUI:04C3E69*
+ ID_OUI_FROM_DATABASE=Ekin Teknoloji San ve Tic A.S.
+
+OUI:04C3E6A*
+ ID_OUI_FROM_DATABASE=Sealed Unit Parts Co., Inc.
+
+OUI:04C3E6B*
+ ID_OUI_FROM_DATABASE=Flintec UK Ltd.
+
+OUI:04C3E6C*
+ ID_OUI_FROM_DATABASE=SHANTOU YINGSHENG IMPORT & EXPORT TRADING CO.,LTD.
+
+OUI:04C3E6D*
+ ID_OUI_FROM_DATABASE=Amiosec Ltd
+
+OUI:04C3E6E*
+ ID_OUI_FROM_DATABASE=Teleepoch Ltd
+
OUI:04C5A4*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -40005,7 +40101,7 @@ OUI:08004D*
ID_OUI_FROM_DATABASE=CORVUS SYSTEMS INC.
OUI:08004E*
- ID_OUI_FROM_DATABASE=3COM EUROPE LTD.
+ ID_OUI_FROM_DATABASE=3COM EUROPE LTD
OUI:08004F*
ID_OUI_FROM_DATABASE=CYGNET SYSTEMS
@@ -40298,6 +40394,9 @@ OUI:0823B2*
OUI:082522*
ID_OUI_FROM_DATABASE=ADVANSEE
+OUI:082525*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:082719*
ID_OUI_FROM_DATABASE=APS systems/electronic AG
@@ -40508,6 +40607,9 @@ OUI:088E4F*
OUI:088F2C*
ID_OUI_FROM_DATABASE=Hills Sound Vision & Lighting
+OUI:0890BA*
+ ID_OUI_FROM_DATABASE=Danlaw Inc
+
OUI:0894EF*
ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation
@@ -40637,6 +40739,9 @@ OUI:08D42B*
OUI:08D46A*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+OUI:08D59D*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:08D5C0*
ID_OUI_FROM_DATABASE=Seers Technology Co., Ltd
@@ -40814,6 +40919,9 @@ OUI:0C1A10*
OUI:0C1C20*
ID_OUI_FROM_DATABASE=Kakao Corp
+OUI:0C1C57*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:0C1DAF*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
@@ -40841,6 +40949,9 @@ OUI:0C2755*
OUI:0C2A69*
ID_OUI_FROM_DATABASE=electric imp, incorporated
+OUI:0C2A86*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:0C2AE7*
ID_OUI_FROM_DATABASE=Beijing General Research Institute of Mining and Metallurgy
@@ -40919,6 +41030,9 @@ OUI:0C51F7*
OUI:0C5203*
ID_OUI_FROM_DATABASE=AGM GROUP LIMITED
+OUI:0C5331*
+ ID_OUI_FROM_DATABASE=ETH Zurich
+
OUI:0C5415*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -41060,6 +41174,9 @@ OUI:0C75BD*
OUI:0C771A*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:0C7C28*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:0C7D7C*
ID_OUI_FROM_DATABASE=Kexiang Information Technology Co, Ltd.
@@ -41105,6 +41222,9 @@ OUI:0C8BD3*
OUI:0C8BFD*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:0C8C24*
+ ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD
+
OUI:0C8C8F*
ID_OUI_FROM_DATABASE=Kamo Technology Limited
@@ -41135,15 +41255,24 @@ OUI:0C93FB*
OUI:0C96BF*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:0C96E6*
+ ID_OUI_FROM_DATABASE=Cloud Network Technology (Samoa) Limited
+
OUI:0C9838*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+OUI:0C9A42*
+ ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED
+
OUI:0C9B13*
ID_OUI_FROM_DATABASE=Shanghai Magic Mobile Telecommunication Co.Ltd.
OUI:0C9D56*
ID_OUI_FROM_DATABASE=Consort Controls Ltd
+OUI:0C9D92*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
OUI:0C9E91*
ID_OUI_FROM_DATABASE=Sankosha Corporation
@@ -41189,6 +41318,9 @@ OUI:0CB459*
OUI:0CB4EF*
ID_OUI_FROM_DATABASE=Digience Co.,Ltd.
+OUI:0CB527*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:0CB5DE*
ID_OUI_FROM_DATABASE=Alcatel Lucent
@@ -41246,6 +41378,9 @@ OUI:0CC81F*
OUI:0CC9C6*
ID_OUI_FROM_DATABASE=Samwin Hong Kong Limited
+OUI:0CCB85*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+
OUI:0CCB8D*
ID_OUI_FROM_DATABASE=ASCO Numatics GmbH
@@ -41672,6 +41807,9 @@ OUI:1056CA*
OUI:105887*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:105917*
+ ID_OUI_FROM_DATABASE=Tonal
+
OUI:105AF7*
ID_OUI_FROM_DATABASE=ADB Italia
@@ -41696,6 +41834,9 @@ OUI:1062C9*
OUI:1062D0*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+OUI:1062E5*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
OUI:1062EB*
ID_OUI_FROM_DATABASE=D-Link International
@@ -41813,6 +41954,9 @@ OUI:109FA9*
OUI:10A13B*
ID_OUI_FROM_DATABASE=FUJIKURA RUBBER LTD.
+OUI:10A24E*
+ ID_OUI_FROM_DATABASE=GOLD3LINK ELECTRONICS CO., LTD
+
OUI:10A4B9*
ID_OUI_FROM_DATABASE=Baidu Online Network Technology (Beijing) Co., Ltd
@@ -42149,6 +42293,9 @@ OUI:141FBAF*
OUI:14205E*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:142233*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:1422DB*
ID_OUI_FROM_DATABASE=eero inc.
@@ -42206,6 +42353,9 @@ OUI:143605*
OUI:1436C6*
ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd.
+OUI:143719*
+ ID_OUI_FROM_DATABASE=PT Prakarsa Visi Valutama
+
OUI:14373B*
ID_OUI_FROM_DATABASE=PROCOM Systems
@@ -42239,6 +42389,9 @@ OUI:14444A*
OUI:1446E4*
ID_OUI_FROM_DATABASE=AVISTEL
+OUI:144802*
+ ID_OUI_FROM_DATABASE=THE YEOLRIM Co.,Ltd.
+
OUI:14488B*
ID_OUI_FROM_DATABASE=Shenzhen Doov Technology Co.,Ltd
@@ -42320,6 +42473,9 @@ OUI:14579F*
OUI:1458D0*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:1459C0*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
OUI:145A05*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -42416,9 +42572,15 @@ OUI:149182*
OUI:149346*
ID_OUI_FROM_DATABASE=PNI sensor corporation
+OUI:14942F*
+ ID_OUI_FROM_DATABASE=USYS CO.,LTD.
+
OUI:149448*
ID_OUI_FROM_DATABASE=BLU CASTLE S.A.
+OUI:1496E5*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:14987D*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
@@ -42527,9 +42689,15 @@ OUI:14C21D*
OUI:14C3C2*
ID_OUI_FROM_DATABASE=K.A. Schmersal GmbH & Co. KG
+OUI:14C697*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:14C913*
ID_OUI_FROM_DATABASE=LG Electronics
+OUI:14CAA0*
+ ID_OUI_FROM_DATABASE=Hu&Co
+
OUI:14CC20*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
@@ -42545,6 +42713,9 @@ OUI:14CFE2*
OUI:14D11F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:14D169*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:14D4FE*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -42575,6 +42746,9 @@ OUI:14E6E4*
OUI:14E7C8*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+OUI:14E9B2*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:14EB33*
ID_OUI_FROM_DATABASE=BSMediasoft Co., Ltd.
@@ -42612,7 +42786,7 @@ OUI:14FEB5*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:18002D*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:1800DB*
ID_OUI_FROM_DATABASE=Fitbit Inc.
@@ -42677,6 +42851,9 @@ OUI:18193F*
OUI:181BEB*
ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
+OUI:181DEA*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:181E78*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
@@ -42758,6 +42935,9 @@ OUI:18396E*
OUI:183A2D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:183A48*
+ ID_OUI_FROM_DATABASE=VostroNet
+
OUI:183BD2*
ID_OUI_FROM_DATABASE=BYD Precision Manufacture Company Ltd.
@@ -42818,6 +42998,9 @@ OUI:1853E0*
OUI:18550F*
ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:185680*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:185933*
ID_OUI_FROM_DATABASE=Cisco SPVTG
@@ -42842,6 +43025,9 @@ OUI:1861C7*
OUI:18622C*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:1862E4*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:186472*
ID_OUI_FROM_DATABASE=Aruba Networks
@@ -42941,6 +43127,9 @@ OUI:188857*
OUI:18895B*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:1889A0*
+ ID_OUI_FROM_DATABASE=Wuhan Funshion Online Technologies Co.,Ltd
+
OUI:1889DF*
ID_OUI_FROM_DATABASE=CerebrEX Inc.
@@ -42965,6 +43154,9 @@ OUI:1890D8*
OUI:18922C*
ID_OUI_FROM_DATABASE=Virtual Instruments
+OUI:18937F*
+ ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
+
OUI:1893D7*
ID_OUI_FROM_DATABASE=Texas Instruments
@@ -43058,6 +43250,9 @@ OUI:18AA45*
OUI:18ABF5*
ID_OUI_FROM_DATABASE=Ultra Electronics Electrics
+OUI:18AC9E*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
OUI:18AD4D*
ID_OUI_FROM_DATABASE=Polostar Technology Corporation
@@ -43106,6 +43301,9 @@ OUI:18C086*
OUI:18C19D*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+OUI:18C2BF*
+ ID_OUI_FROM_DATABASE=BUFFALO.INC
+
OUI:18C451*
ID_OUI_FROM_DATABASE=Tucson Embedded Systems
@@ -43148,6 +43346,9 @@ OUI:18D6C7*
OUI:18D6CF*
ID_OUI_FROM_DATABASE=Kurth Electronic GmbH
+OUI:18D717*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:18D949*
ID_OUI_FROM_DATABASE=Qvis Labs, LLC
@@ -43181,6 +43382,9 @@ OUI:18E7F4*
OUI:18E80F*
ID_OUI_FROM_DATABASE=Viking Electronics Inc.
+OUI:18E829*
+ ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
+
OUI:18E8DD*
ID_OUI_FROM_DATABASE=MODULETEK
@@ -43289,6 +43493,9 @@ OUI:1C1B0D*
OUI:1C1B68*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:1C1BB5*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:1C1CFD*
ID_OUI_FROM_DATABASE=Dalian Hi-Think Computer Technology, Corp
@@ -43548,7 +43755,7 @@ OUI:1C7839*
ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd.
OUI:1C7B21*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:1C7B23*
ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd.
@@ -43985,6 +44192,9 @@ OUI:1CC1DE*
OUI:1CC316*
ID_OUI_FROM_DATABASE=MileSight Technology Co., Ltd.
+OUI:1CC3EB*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:1CC586*
ID_OUI_FROM_DATABASE=Absolute Acoustics
@@ -44165,6 +44375,9 @@ OUI:2012D5*
OUI:2013E0*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:20163D*
+ ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+
OUI:2016B9*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -44289,7 +44502,7 @@ OUI:2053CA*
ID_OUI_FROM_DATABASE=Risk Technology Ltd
OUI:205476*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:2054FA*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -44466,7 +44679,7 @@ OUI:20A787*
ID_OUI_FROM_DATABASE=Bointec Taiwan Corporation Limited
OUI:20A8B9*
- ID_OUI_FROM_DATABASE=Siemens
+ ID_OUI_FROM_DATABASE=SIEMENS AG
OUI:20A90E*
ID_OUI_FROM_DATABASE=TCT mobile ltd
@@ -44567,6 +44780,9 @@ OUI:20D607*
OUI:20D75A*
ID_OUI_FROM_DATABASE=Posh Mobile Limited
+OUI:20D80B*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:20D906*
ID_OUI_FROM_DATABASE=Iota, Inc.
@@ -44579,6 +44795,9 @@ OUI:20DC93*
OUI:20DCE6*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:20DE88*
+ ID_OUI_FROM_DATABASE=IC Realtime LLC
+
OUI:20DF3F*
ID_OUI_FROM_DATABASE=Nanjing SAC Power Grid Automation Co., Ltd.
@@ -44600,6 +44819,9 @@ OUI:20E564*
OUI:20E791*
ID_OUI_FROM_DATABASE=Siemens Healthcare Diagnostics, Inc
+OUI:20E882*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:20EAC7*
ID_OUI_FROM_DATABASE=SHENZHEN RIOPINE ELECTRONICS CO., LTD
@@ -44636,6 +44858,9 @@ OUI:20F510*
OUI:20F543*
ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD
+OUI:20F77C*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:20F85E*
ID_OUI_FROM_DATABASE=Delta Electronics
@@ -44660,6 +44885,9 @@ OUI:2401C7*
OUI:24050F*
ID_OUI_FROM_DATABASE=MTN Electronic Co. Ltd
+OUI:240588*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
OUI:2405F5*
ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
@@ -44738,8 +44966,11 @@ OUI:241FA0*
OUI:2420C7*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:242124*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:2421AB*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:24240E*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -44753,6 +44984,9 @@ OUI:2429FE*
OUI:242E02*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:242E90*
+ ID_OUI_FROM_DATABASE=PALIT MICROSYSTEMS, LTD
+
OUI:242FFA*
ID_OUI_FROM_DATABASE=Toshiba Global Commerce Solutions
@@ -44771,6 +45005,9 @@ OUI:24374C*
OUI:2437EF*
ID_OUI_FROM_DATABASE=EMC Electronic Media Communication SA
+OUI:243A82*
+ ID_OUI_FROM_DATABASE=IRTS
+
OUI:243C20*
ID_OUI_FROM_DATABASE=Dynamode Group
@@ -44798,6 +45035,9 @@ OUI:244B81*
OUI:244C07*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:244CE3*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:244E7B0*
ID_OUI_FROM_DATABASE=Tekelek Europe Ltd
@@ -44933,6 +45173,9 @@ OUI:247C4C*
OUI:247E12*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:247E51*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:247F20*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
@@ -45107,9 +45350,15 @@ OUI:24D13F*
OUI:24D2CC*
ID_OUI_FROM_DATABASE=SmartDrive Systems Inc.
+OUI:24D3F2*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:24D51C*
ID_OUI_FROM_DATABASE=Zhongtian broadband technology co., LTD
+OUI:24D76B*
+ ID_OUI_FROM_DATABASE=Syntronic AB
+
OUI:24D921*
ID_OUI_FROM_DATABASE=Avaya Inc
@@ -45203,6 +45452,15 @@ OUI:24F5AA*
OUI:24F677*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:24FAF3*
+ ID_OUI_FROM_DATABASE=Shanghai Flexem Technology Co.,Ltd.
+
+OUI:24FB65*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:24FCE5*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:24FD52*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -45359,6 +45617,9 @@ OUI:2830AC*
OUI:283152*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:283166*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:2832C5*
ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
@@ -45422,6 +45683,9 @@ OUI:283713*
OUI:283737*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:28385C*
+ ID_OUI_FROM_DATABASE=FLEXTRONICS
+
OUI:2838CF*
ID_OUI_FROM_DATABASE=Gen2wave
@@ -45431,6 +45695,9 @@ OUI:28395E*
OUI:2839E7*
ID_OUI_FROM_DATABASE=Preceno Technology Pte.Ltd.
+OUI:283A4D*
+ ID_OUI_FROM_DATABASE=Cloud Network Technology (Samoa) Limited
+
OUI:283B82*
ID_OUI_FROM_DATABASE=D-Link International
@@ -45440,8 +45707,11 @@ OUI:283B96*
OUI:283CE4*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:283E76*
+ ID_OUI_FROM_DATABASE=Common Networks
+
OUI:283F69*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:28401A*
ID_OUI_FROM_DATABASE=C8 MediSensors, Inc.
@@ -45507,11 +45777,14 @@ OUI:286094*
ID_OUI_FROM_DATABASE=CAPELEC
OUI:286336*
- ID_OUI_FROM_DATABASE=Siemens AG - Industrial Automation - EWA
+ ID_OUI_FROM_DATABASE=Siemens AG
OUI:28656B*
ID_OUI_FROM_DATABASE=Keystone Microtech Corporation
+OUI:2866E3*
+ ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+
OUI:286AB8*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -45524,6 +45797,9 @@ OUI:286C07*
OUI:286D97*
ID_OUI_FROM_DATABASE=SAMJIN Co., Ltd.
+OUI:286DCD*
+ ID_OUI_FROM_DATABASE=Beijing Winner Microelectronics Co.,Ltd.
+
OUI:286ED4*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -45611,9 +45887,15 @@ OUI:289A4B*
OUI:289AFA*
ID_OUI_FROM_DATABASE=TCT mobile ltd
+OUI:289E97*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:289EDF*
ID_OUI_FROM_DATABASE=Danfoss Turbocor Compressors, Inc
+OUI:289EFC*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:28A02B*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -45761,6 +46043,9 @@ OUI:28CFDA*
OUI:28CFE9*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:28D0CB*
+ ID_OUI_FROM_DATABASE=Cambridge Communication Systems Ltd
+
OUI:28D1AF*
ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -46016,6 +46301,12 @@ OUI:2C0E3D*
OUI:2C10C1*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+OUI:2C15E1*
+ ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd.
+
+OUI:2C1875*
+ ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd
+
OUI:2C18AE*
ID_OUI_FROM_DATABASE=Trend Electronics Co., Ltd.
@@ -46475,6 +46766,9 @@ OUI:2C7B5A*
OUI:2C7B84*
ID_OUI_FROM_DATABASE=OOO Petr Telegin
+OUI:2C7CE4*
+ ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd.
+
OUI:2C7E81*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -46775,6 +47069,51 @@ OUI:30055C*
OUI:30074D*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
+OUI:3009F90*
+ ID_OUI_FROM_DATABASE=Hurray Cloud Technology Co., Ltd.
+
+OUI:3009F91*
+ ID_OUI_FROM_DATABASE=Shenzhen Sunvell Electronics Co., Ltd.
+
+OUI:3009F92*
+ ID_OUI_FROM_DATABASE=Beijing Netswift Technology Co.,Ltd.
+
+OUI:3009F93*
+ ID_OUI_FROM_DATABASE=OOO Microlink-Svyaz
+
+OUI:3009F94*
+ ID_OUI_FROM_DATABASE=Punkt Tronics AG
+
+OUI:3009F95*
+ ID_OUI_FROM_DATABASE=VELSITEC-CLIBASE
+
+OUI:3009F96*
+ ID_OUI_FROM_DATABASE=Beijing Mydreamplus Information Technology Co., Ltd.
+
+OUI:3009F97*
+ ID_OUI_FROM_DATABASE=Maytronics Ltd.
+
+OUI:3009F98*
+ ID_OUI_FROM_DATABASE=essence security
+
+OUI:3009F99*
+ ID_OUI_FROM_DATABASE=Bonraybio
+
+OUI:3009F9A*
+ ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd.
+
+OUI:3009F9B*
+ ID_OUI_FROM_DATABASE=Sichuan Nebula Networks Co.,LTD.
+
+OUI:3009F9C*
+ ID_OUI_FROM_DATABASE=Honeywell
+
+OUI:3009F9D*
+ ID_OUI_FROM_DATABASE=Technology for Humankind
+
+OUI:3009F9E*
+ ID_OUI_FROM_DATABASE=ZhongLi HengFeng (Shenzhen) Technology co.,Ltd.
+
OUI:300AC5*
ID_OUI_FROM_DATABASE=Ruio telecommunication technologies Co., Limited
@@ -46815,7 +47154,7 @@ OUI:30168D*
ID_OUI_FROM_DATABASE=ProLon
OUI:3017C8*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:3018CF*
ID_OUI_FROM_DATABASE=DEOS control systems GmbH
@@ -46874,6 +47213,12 @@ OUI:301F9AE*
OUI:30215B*
ID_OUI_FROM_DATABASE=Shenzhen Ostar Display Electronic Co.,Ltd
+OUI:302303*
+ ID_OUI_FROM_DATABASE=Belkin International Inc.
+
+OUI:302432*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:3029BE*
ID_OUI_FROM_DATABASE=Shanghai MRDcom Co.,Ltd
@@ -46902,7 +47247,7 @@ OUI:303855*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:303926*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:303955*
ID_OUI_FROM_DATABASE=Shenzhen Jinhengjia Electronic Co., Ltd.
@@ -46925,6 +47270,9 @@ OUI:304174*
OUI:304225*
ID_OUI_FROM_DATABASE=BURG-WÄCHTER KG
+OUI:3042A1*
+ ID_OUI_FROM_DATABASE=ilumisys Inc. DBA Toggled
+
OUI:304449*
ID_OUI_FROM_DATABASE=PLATH GmbH
@@ -46946,6 +47294,9 @@ OUI:30469A*
OUI:30493B*
ID_OUI_FROM_DATABASE=Nanjing Z-Com Wireless Co.,Ltd
+OUI:304B07*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+
OUI:304C7E*
ID_OUI_FROM_DATABASE=Panasonic Electric Works Automation Controls Techno Co.,Ltd.
@@ -46982,6 +47333,9 @@ OUI:305A3A*
OUI:305D38*
ID_OUI_FROM_DATABASE=Beissbarth
+OUI:305DA6*
+ ID_OUI_FROM_DATABASE=ADVALY SYSTEM Inc.
+
OUI:306023*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -47022,7 +47376,7 @@ OUI:307496*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:307512*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:30766F*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
@@ -47111,6 +47465,9 @@ OUI:309C23*
OUI:309FFB*
ID_OUI_FROM_DATABASE=Ardomus Networks Corporation
+OUI:30A1FA*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:30A220*
ID_OUI_FROM_DATABASE=ARG Telecom
@@ -47118,7 +47475,7 @@ OUI:30A243*
ID_OUI_FROM_DATABASE=Shenzhen Prifox Innovation Technology Co., Ltd.
OUI:30A8DB*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:30A9DE*
ID_OUI_FROM_DATABASE=LG Innotek
@@ -47189,6 +47546,9 @@ OUI:30CBF8*
OUI:30CDA7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:30D16B*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
OUI:30D17E*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -47207,6 +47567,9 @@ OUI:30D46A*
OUI:30D587*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:30D659*
+ ID_OUI_FROM_DATABASE=Merging Technologies SA
+
OUI:30D6C9*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -47411,6 +47774,9 @@ OUI:3408BC*
OUI:340A22*
ID_OUI_FROM_DATABASE=TOP-ACCESS ELECTRONICS CO LTD
+OUI:340A98*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:340AFF*
ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd.
@@ -47426,6 +47792,9 @@ OUI:341290*
OUI:341298*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:3412F9*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:3413A8*
ID_OUI_FROM_DATABASE=Mediplan Limited
@@ -47474,9 +47843,15 @@ OUI:34255D*
OUI:342606*
ID_OUI_FROM_DATABASE=CarePredict, Inc.
+OUI:342792*
+ ID_OUI_FROM_DATABASE=FREEBOX SAS
+
OUI:3428F0*
ID_OUI_FROM_DATABASE=ATN International Limited
+OUI:342912*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:34298F0*
ID_OUI_FROM_DATABASE=BlackEdge Capital
@@ -47528,9 +47903,15 @@ OUI:3429EA*
OUI:342AF1*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:342CC4*
+ ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc.
+
OUI:342D0D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:342EB6*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:342F6E*
ID_OUI_FROM_DATABASE=Anywire corporation
@@ -47615,6 +47996,9 @@ OUI:345760*
OUI:345A06*
ID_OUI_FROM_DATABASE=SHARP Corporation
+OUI:345ABA*
+ ID_OUI_FROM_DATABASE=tcloud intelligence
+
OUI:345B11*
ID_OUI_FROM_DATABASE=EVI HEAT AB
@@ -47636,6 +48020,9 @@ OUI:346288*
OUI:3464A9*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:3466EA*
+ ID_OUI_FROM_DATABASE=VERTU INTERNATIONAL CORPORATION LIMITED
+
OUI:34684A*
ID_OUI_FROM_DATABASE=Teraworks Co., Ltd.
@@ -47684,6 +48071,9 @@ OUI:347877*
OUI:3478D7*
ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co.,Ltd.
+OUI:347916*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:347A60*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -47699,6 +48089,9 @@ OUI:347E5C*
OUI:347ECA*
ID_OUI_FROM_DATABASE=NEXTWILL
+OUI:34800D*
+ ID_OUI_FROM_DATABASE=Cavium Inc
+
OUI:3480B3*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
@@ -47847,7 +48240,7 @@ OUI:34BA51*
ID_OUI_FROM_DATABASE=Se-Kure Controls, Inc.
OUI:34BA75*
- ID_OUI_FROM_DATABASE=Tembo Systems, Inc.
+ ID_OUI_FROM_DATABASE=Everest Networks, Inc
OUI:34BA9A*
ID_OUI_FROM_DATABASE=Asiatelco Technologies Co.
@@ -48002,6 +48395,9 @@ OUI:34E0CF*
OUI:34E0D7*
ID_OUI_FROM_DATABASE=DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD
+OUI:34E12D*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:34E2FD*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -48011,6 +48407,9 @@ OUI:34E380*
OUI:34E42A*
ID_OUI_FROM_DATABASE=Automatic Bar Controls Inc.
+OUI:34E5EC*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
OUI:34E6AD*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -48365,6 +48764,9 @@ OUI:386C9B*
OUI:386E21*
ID_OUI_FROM_DATABASE=Wasion Group Ltd.
+OUI:386E88*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:386EA2*
ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
@@ -48429,7 +48831,7 @@ OUI:3876D1*
ID_OUI_FROM_DATABASE=Euronda SpA
OUI:387862*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:387B47*
ID_OUI_FROM_DATABASE=AKELA, Inc.
@@ -48452,6 +48854,9 @@ OUI:3889DC*
OUI:388AB7*
ID_OUI_FROM_DATABASE=ITC Networks
+OUI:388B59*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
OUI:388C50*
ID_OUI_FROM_DATABASE=LG Electronics
@@ -48771,7 +49176,7 @@ OUI:38FDFE1*
ID_OUI_FROM_DATABASE=WAYTONE (BEIIJNG) COMMUNICATIONS CO.,LTD
OUI:38FDFE2*
- ID_OUI_FROM_DATABASE=B.U.G.SST,Inc
+ ID_OUI_FROM_DATABASE=Smart Solution Technology, Inc
OUI:38FDFE3*
ID_OUI_FROM_DATABASE=Siemens AG, PG IE R&D
@@ -49064,6 +49469,51 @@ OUI:3C3F51*
OUI:3C404F*
ID_OUI_FROM_DATABASE=GUANGDONG PISEN ELECTRONICS CO.,LTD
+OUI:3C427E0*
+ ID_OUI_FROM_DATABASE=Grandway Technology (Shenzhen) Limited
+
+OUI:3C427E1*
+ ID_OUI_FROM_DATABASE=Dongguan Taide Industrial Co.,Ltd.
+
+OUI:3C427E2*
+ ID_OUI_FROM_DATABASE=Starloop Tech Co., Ltd.
+
+OUI:3C427E3*
+ ID_OUI_FROM_DATABASE=Shenzhen VETAS Communication Technology Co , Ltd.
+
+OUI:3C427E4*
+ ID_OUI_FROM_DATABASE=Teknoware Oy
+
+OUI:3C427E5*
+ ID_OUI_FROM_DATABASE=Geoplan Korea
+
+OUI:3C427E6*
+ ID_OUI_FROM_DATABASE=Edit Srl
+
+OUI:3C427E7*
+ ID_OUI_FROM_DATABASE=GJS Co., Ltd.
+
+OUI:3C427E8*
+ ID_OUI_FROM_DATABASE=UBTECH ROBOTICS CORP
+
+OUI:3C427E9*
+ ID_OUI_FROM_DATABASE=TAITEX CORPORATION
+
+OUI:3C427EA*
+ ID_OUI_FROM_DATABASE=snap40 Ltd
+
+OUI:3C427EB*
+ ID_OUI_FROM_DATABASE=Compal Electronics INC.
+
+OUI:3C427EC*
+ ID_OUI_FROM_DATABASE=Privacy Labs
+
+OUI:3C427ED*
+ ID_OUI_FROM_DATABASE=ROBOX SMART MOTION (WUHU) CO.,LTD
+
+OUI:3C427EE*
+ ID_OUI_FROM_DATABASE=Xiaoniu network technology (Shanghai) Co., Ltd.
+
OUI:3C438E*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -49169,6 +49619,9 @@ OUI:3C6FF7*
OUI:3C7059*
ID_OUI_FROM_DATABASE=MakerBot Industries
+OUI:3C71BF*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:3C7437*
ID_OUI_FROM_DATABASE=RIM
@@ -49214,6 +49667,9 @@ OUI:3C86A8*
OUI:3C8970*
ID_OUI_FROM_DATABASE=Neosfar
+OUI:3C8994*
+ ID_OUI_FROM_DATABASE=BSkyB Ltd
+
OUI:3C89A6*
ID_OUI_FROM_DATABASE=KAPELSE
@@ -49262,6 +49718,9 @@ OUI:3C970E*
OUI:3C977E*
ID_OUI_FROM_DATABASE=IPS Technology Limited
+OUI:3C9872*
+ ID_OUI_FROM_DATABASE=Sercomm Corporation.
+
OUI:3C98BF*
ID_OUI_FROM_DATABASE=Quest Controls, Inc.
@@ -49559,6 +50018,9 @@ OUI:40169F*
OUI:4016FA*
ID_OUI_FROM_DATABASE=EKM Metering
+OUI:4017E2*
+ ID_OUI_FROM_DATABASE=INTAI TECHNOLOGY CORP.
+
OUI:4018B1*
ID_OUI_FROM_DATABASE=Aerohive Networks Inc.
@@ -49584,7 +50046,7 @@ OUI:402814*
ID_OUI_FROM_DATABASE=RFI Engineering
OUI:402BA1*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:402CF4*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
@@ -49598,6 +50060,9 @@ OUI:403004*
OUI:403067*
ID_OUI_FROM_DATABASE=Conlog (Pty) Ltd
+OUI:40313C*
+ ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD
+
OUI:40331A*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -49623,7 +50088,7 @@ OUI:40406B*
ID_OUI_FROM_DATABASE=Icomera
OUI:4040A7*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:404229*
ID_OUI_FROM_DATABASE=Layer3TV, Inc
@@ -49730,6 +50195,9 @@ OUI:40560C*
OUI:40562D*
ID_OUI_FROM_DATABASE=Smartron India Pvt ltd
+OUI:405662*
+ ID_OUI_FROM_DATABASE=GuoTengShengHua Electronics LTD.
+
OUI:405A9B*
ID_OUI_FROM_DATABASE=ANOVO
@@ -49763,6 +50231,9 @@ OUI:406231*
OUI:4062B6*
ID_OUI_FROM_DATABASE=Tele system communication
+OUI:4062EA*
+ ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
+
OUI:4064A4*
ID_OUI_FROM_DATABASE=THE FURUKAWA ELECTRIC CO., LTD
@@ -49898,6 +50369,9 @@ OUI:409F87*
OUI:409FC7*
ID_OUI_FROM_DATABASE=BAEKCHUN I&C Co., Ltd.
+OUI:40A108*
+ ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.
+
OUI:40A36B0*
ID_OUI_FROM_DATABASE=Fin Robotics Inc
@@ -50001,7 +50475,7 @@ OUI:40B7F3*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:40B837*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:40B89A*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -50030,6 +50504,9 @@ OUI:40BF17*
OUI:40C245*
ID_OUI_FROM_DATABASE=Shenzhen Hexicom Technology Co., Ltd.
+OUI:40C3C6*
+ ID_OUI_FROM_DATABASE=SnapRoute
+
OUI:40C4D6*
ID_OUI_FROM_DATABASE=ChongQing Camyu Technology Development Co.,Ltd.
@@ -50042,6 +50519,9 @@ OUI:40C729*
OUI:40C7C9*
ID_OUI_FROM_DATABASE=Naviit Inc.
+OUI:40C81F*
+ ID_OUI_FROM_DATABASE=Shenzhen Xinguodu Technology Co., Ltd.
+
OUI:40C8CB*
ID_OUI_FROM_DATABASE=AM Telecom co., Ltd.
@@ -50084,6 +50564,9 @@ OUI:40D63C*
OUI:40D855*
ID_OUI_FROM_DATABASE=IEEE Registration Authority
+OUI:40DC9D*
+ ID_OUI_FROM_DATABASE=HAJEN
+
OUI:40E230*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
@@ -50147,6 +50630,9 @@ OUI:40ED98D*
OUI:40ED98E*
ID_OUI_FROM_DATABASE=BORDA TECHNOLOGY
+OUI:40EEDD*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:40EF4C*
ID_OUI_FROM_DATABASE=Fihonest communication co.,Ltd
@@ -50285,6 +50771,9 @@ OUI:441E98*
OUI:441EA1*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:4422F1*
+ ID_OUI_FROM_DATABASE=S.FAC, INC
+
OUI:4423AA*
ID_OUI_FROM_DATABASE=Farmage Co., Ltd.
@@ -50369,6 +50858,9 @@ OUI:444A65*
OUI:444AB0*
ID_OUI_FROM_DATABASE=Zhejiang Moorgen Intelligence Technology Co., Ltd
+OUI:444B5D*
+ ID_OUI_FROM_DATABASE=GE Healthcare
+
OUI:444C0C*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -50432,6 +50924,9 @@ OUI:44650D*
OUI:44656A*
ID_OUI_FROM_DATABASE=Mega Video Electronic(HK) Industry Co., Ltd
+OUI:44657F*
+ ID_OUI_FROM_DATABASE=Calix Inc.
+
OUI:44666E*
ID_OUI_FROM_DATABASE=IP-LINE
@@ -50472,7 +50967,7 @@ OUI:4473D6*
ID_OUI_FROM_DATABASE=Logitech
OUI:44746C*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:44783E*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -50570,6 +51065,9 @@ OUI:449F7F*
OUI:44A42D*
ID_OUI_FROM_DATABASE=TCT mobile ltd
+OUI:44A466*
+ ID_OUI_FROM_DATABASE=GROUPE LDLC
+
OUI:44A689*
ID_OUI_FROM_DATABASE=PROMAX ELECTRONICA SA
@@ -50673,7 +51171,7 @@ OUI:44D437*
ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB
OUI:44D4E0*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:44D5A5*
ID_OUI_FROM_DATABASE=AddOn Computer
@@ -50711,6 +51209,9 @@ OUI:44E49A*
OUI:44E4D9*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:44E4EE*
+ ID_OUI_FROM_DATABASE=Wistron Neweb Corporation
+
OUI:44E8A5*
ID_OUI_FROM_DATABASE=Myreka Technologies Sdn. Bhd.
@@ -50870,6 +51371,9 @@ OUI:48282F*
OUI:482AE3*
ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
+OUI:482CA0*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:482CEA*
ID_OUI_FROM_DATABASE=Motorola Inc Business Light Radios
@@ -50918,6 +51422,9 @@ OUI:4846FB*
OUI:4849C7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:484AE9*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
OUI:484BAA*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -50942,6 +51449,9 @@ OUI:48555C*
OUI:48555F*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:485702*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:4857DD*
ID_OUI_FROM_DATABASE=Facebook Inc
@@ -50966,6 +51476,9 @@ OUI:485D36*
OUI:485D60*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+OUI:485F99*
+ ID_OUI_FROM_DATABASE=Cloud Network Technology (Samoa) Limited
+
OUI:48605F*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
@@ -51023,6 +51536,9 @@ OUI:4865EED*
OUI:4865EEE*
ID_OUI_FROM_DATABASE=CNU
+OUI:486834*
+ ID_OUI_FROM_DATABASE=Silicon Motion, Inc.
+
OUI:486B2C*
ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD.
@@ -51047,6 +51563,9 @@ OUI:487119*
OUI:48746E*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:487583*
+ ID_OUI_FROM_DATABASE=Intellion AG
+
OUI:487604*
ID_OUI_FROM_DATABASE=Private
@@ -51077,6 +51596,9 @@ OUI:4886E8*
OUI:488803*
ID_OUI_FROM_DATABASE=ManTechnology Inc.
+OUI:48881E*
+ ID_OUI_FROM_DATABASE=EthoSwitch LLC
+
OUI:4888CA*
ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.
@@ -51098,6 +51620,9 @@ OUI:489153*
OUI:4891F6*
ID_OUI_FROM_DATABASE=Shenzhen Reach software technology CO.,LTD
+OUI:4898CA*
+ ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd.
+
OUI:489A42*
ID_OUI_FROM_DATABASE=Technomate Ltd
@@ -51110,6 +51635,9 @@ OUI:489D18*
OUI:489D24*
ID_OUI_FROM_DATABASE=BlackBerry RTS
+OUI:48A0F8*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:48A195*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -51122,6 +51650,9 @@ OUI:48A2B7*
OUI:48A380*
ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co.,Ltd.
+OUI:48A472*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:48A6D2*
ID_OUI_FROM_DATABASE=GJsun Optical Science and Tech Co.,Ltd.
@@ -51287,6 +51818,9 @@ OUI:48EE0C*
OUI:48EE86*
ID_OUI_FROM_DATABASE=UTStarcom (China) Co.,Ltd
+OUI:48F027*
+ ID_OUI_FROM_DATABASE=Chengdu newifi Co.,Ltd
+
OUI:48F07B*
ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
@@ -51332,6 +51866,9 @@ OUI:48FEEA*
OUI:4C0082*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:4C0143*
+ ID_OUI_FROM_DATABASE=eero inc.
+
OUI:4C022E*
ID_OUI_FROM_DATABASE=CMR KOREA CO., LTD
@@ -51365,9 +51902,15 @@ OUI:4C0F6E*
OUI:4C0FC7*
ID_OUI_FROM_DATABASE=Earda Technologies co Ltd
+OUI:4C1159*
+ ID_OUI_FROM_DATABASE=Vision Information & Communications
+
OUI:4C11BF*
ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd.
+OUI:4C1265*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:4C1365*
ID_OUI_FROM_DATABASE=Emplus Technologies
@@ -51401,11 +51944,14 @@ OUI:4C1A3D*
OUI:4C1A95*
ID_OUI_FROM_DATABASE=Novakon Co., Ltd.
+OUI:4C1B86*
+ ID_OUI_FROM_DATABASE=Arcadyan Corporation
+
OUI:4C1FCC*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:4C21D0*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:4C2258*
ID_OUI_FROM_DATABASE=cozybit, Inc.
@@ -51443,6 +51989,9 @@ OUI:4C334E*
OUI:4C3488*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:4C364E*
+ ID_OUI_FROM_DATABASE=Panasonic Corporation Connected Solutions Company
+
OUI:4C38D5*
ID_OUI_FROM_DATABASE=MITAC COMPUTING TECHNOLOGY CORPORATION
@@ -51791,6 +52340,9 @@ OUI:4CD08A*
OUI:4CD0CB*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:4CD1A1*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:4CD637*
ID_OUI_FROM_DATABASE=Qsono Electronics Co., Ltd
@@ -52067,6 +52619,9 @@ OUI:502E5C*
OUI:502ECE*
ID_OUI_FROM_DATABASE=Asahi Electronics Co.,Ltd
+OUI:502FA8*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:5031AD*
ID_OUI_FROM_DATABASE=ABB Global Industries and Services Private Limited
@@ -52133,6 +52688,9 @@ OUI:504A6E*
OUI:504B5B*
ID_OUI_FROM_DATABASE=CONTROLtronic GmbH
+OUI:504C7E*
+ ID_OUI_FROM_DATABASE=THE 41ST INSTITUTE OF CETC
+
OUI:504EDC*
ID_OUI_FROM_DATABASE=Ping Communication
@@ -52163,6 +52721,9 @@ OUI:5056A8*
OUI:5056BF*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:50579C*
+ ID_OUI_FROM_DATABASE=Seiko Epson Corporation
+
OUI:5057A8*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -52514,6 +53075,9 @@ OUI:50DA00*
OUI:50DCE7*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+OUI:50DCFC*
+ ID_OUI_FROM_DATABASE=ECOCOM
+
OUI:50DD4F*
ID_OUI_FROM_DATABASE=Automation Components, Inc
@@ -52523,6 +53087,9 @@ OUI:50DF95*
OUI:50E0C7*
ID_OUI_FROM_DATABASE=TurControlSystme AG
+OUI:50E0EF*
+ ID_OUI_FROM_DATABASE=Nokia
+
OUI:50E14A*
ID_OUI_FROM_DATABASE=Private
@@ -52664,6 +53231,9 @@ OUI:540955*
OUI:54098D*
ID_OUI_FROM_DATABASE=deister electronic GmbH
+OUI:541031*
+ ID_OUI_FROM_DATABASE=SMARTO
+
OUI:5410EC*
ID_OUI_FROM_DATABASE=Microchip Technology Inc.
@@ -52721,6 +53291,9 @@ OUI:542758*
OUI:54276C*
ID_OUI_FROM_DATABASE=Jiangsu Houge Technology Corp.
+OUI:54278D*
+ ID_OUI_FROM_DATABASE=NXP (China) Management Ltd.
+
OUI:542A9C*
ID_OUI_FROM_DATABASE=LSY Defense, LLC.
@@ -52850,6 +53423,9 @@ OUI:54666C*
OUI:546751*
ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc.
+OUI:546AD8*
+ ID_OUI_FROM_DATABASE=Elster Water Metering Limited
+
OUI:546C0E*
ID_OUI_FROM_DATABASE=Texas Instruments
@@ -52895,6 +53471,9 @@ OUI:547FA8*
OUI:547FEE*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:54812D*
+ ID_OUI_FROM_DATABASE=PAX Computer Technology(Shenzhen) Ltd.
+
OUI:5481AD*
ID_OUI_FROM_DATABASE=Eagle Research Corporation
@@ -53063,6 +53642,9 @@ OUI:54BEF7*
OUI:54BF64*
ID_OUI_FROM_DATABASE=Dell Inc.
+OUI:54C33E*
+ ID_OUI_FROM_DATABASE=Ciena Corporation
+
OUI:54C415*
ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
@@ -53213,6 +53795,9 @@ OUI:5800BB*
OUI:5800E3*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+OUI:5803FB*
+ ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
+
OUI:580454*
ID_OUI_FROM_DATABASE=ICOMM HK LIMITED
@@ -53247,7 +53832,7 @@ OUI:581626*
ID_OUI_FROM_DATABASE=Avaya Inc
OUI:58170C*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:5819F8*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -53288,9 +53873,15 @@ OUI:582AF7*
OUI:582BDB*
ID_OUI_FROM_DATABASE=Pax AB
+OUI:582D34*
+ ID_OUI_FROM_DATABASE=Qingping Electronics (Suzhou) Co., Ltd
+
OUI:582EFE*
ID_OUI_FROM_DATABASE=Lighting Science Group
+OUI:582F40*
+ ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
+
OUI:582F42*
ID_OUI_FROM_DATABASE=Universal Electric Corporation
@@ -53337,7 +53928,7 @@ OUI:584704*
ID_OUI_FROM_DATABASE=Shenzhen Webridge Technology Co.,Ltd
OUI:584822*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:5848C0*
ID_OUI_FROM_DATABASE=COFLEC
@@ -53537,6 +54128,9 @@ OUI:58A0CB*
OUI:58A2B5*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+OUI:58A48E*
+ ID_OUI_FROM_DATABASE=PixArt Imaging Inc.
+
OUI:58A76F*
ID_OUI_FROM_DATABASE=iD corporation
@@ -53561,6 +54155,9 @@ OUI:58B3FC*
OUI:58B42D*
ID_OUI_FROM_DATABASE=YSTen Technology Co.,Ltd
+OUI:58B568*
+ ID_OUI_FROM_DATABASE=SECURITAS DIRECT ESPAÑA, SAU
+
OUI:58B633*
ID_OUI_FROM_DATABASE=Ruckus Wireless
@@ -53603,6 +54200,9 @@ OUI:58C583*
OUI:58C5CB*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:58C876*
+ ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd.
+
OUI:58C935*
ID_OUI_FROM_DATABASE=Chiun Mai Communication Systems, Inc
@@ -53615,6 +54215,9 @@ OUI:58D071*
OUI:58D08F*
ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group
+OUI:58D56E*
+ ID_OUI_FROM_DATABASE=D-Link International
+
OUI:58D67A*
ID_OUI_FROM_DATABASE=TCPlink
@@ -53798,6 +54401,9 @@ OUI:58FCDBF*
OUI:58FD20*
ID_OUI_FROM_DATABASE=Bravida Sakerhet AB
+OUI:58FDBE*
+ ID_OUI_FROM_DATABASE=Shenzhen Taikaida Technology Co., Ltd
+
OUI:5C0038*
ID_OUI_FROM_DATABASE=Viasat Group S.p.A.
@@ -53876,6 +54482,9 @@ OUI:5C254C*
OUI:5C260A*
ID_OUI_FROM_DATABASE=Dell Inc.
+OUI:5C2623*
+ ID_OUI_FROM_DATABASE=WaveLynx Technologies Corporation
+
OUI:5C2AEF*
ID_OUI_FROM_DATABASE=Open Access Pty Ltd
@@ -53996,6 +54605,9 @@ OUI:5C5F67*
OUI:5C63BF*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:5C63C9*
+ ID_OUI_FROM_DATABASE=Intellithings Ltd.
+
OUI:5C6776*
ID_OUI_FROM_DATABASE=IDS Imaging Development Systems GmbH
@@ -54147,7 +54759,7 @@ OUI:5CB43E*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:5CB524*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:5CB559*
ID_OUI_FROM_DATABASE=CNEX Labs
@@ -54185,6 +54797,9 @@ OUI:5CC6E9*
OUI:5CC7D7*
ID_OUI_FROM_DATABASE=AZROAD TECHNOLOGY COMPANY LIMITED
+OUI:5CC999*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:5CC9D3*
ID_OUI_FROM_DATABASE=PALLADIUM ENERGY ELETRONICA DA AMAZONIA LTDA
@@ -54212,6 +54827,9 @@ OUI:5CCF7F*
OUI:5CD135*
ID_OUI_FROM_DATABASE=Xtreme Power Systems
+OUI:5CD20B*
+ ID_OUI_FROM_DATABASE=Yytek Co., Ltd.
+
OUI:5CD2E4*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -54374,6 +54992,9 @@ OUI:5CF9DD*
OUI:5CF9F0*
ID_OUI_FROM_DATABASE=Atomos Engineering P/L
+OUI:5CFB7C*
+ ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd
+
OUI:5CFC66*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -54503,6 +55124,9 @@ OUI:60334B*
OUI:603553*
ID_OUI_FROM_DATABASE=Buwon Technology
+OUI:6035C0*
+ ID_OUI_FROM_DATABASE=SFR
+
OUI:603696*
ID_OUI_FROM_DATABASE=The Sapling Company
@@ -54564,7 +55188,7 @@ OUI:604A1C*
ID_OUI_FROM_DATABASE=SUYIN Corporation
OUI:604BAA*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Magic Leap, Inc.
OUI:6050C1*
ID_OUI_FROM_DATABASE=Kinetek Sports
@@ -54962,6 +55586,9 @@ OUI:60F13D*
OUI:60F189*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:60F18A*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:60F281*
ID_OUI_FROM_DATABASE=TRANWO TECHNOLOGY CO., LTD.
@@ -55067,6 +55694,9 @@ OUI:641225*
OUI:641269*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:641331*
+ ID_OUI_FROM_DATABASE=Bosch Car Multimedia (Wuhu) Co. Ltd.
+
OUI:64136C*
ID_OUI_FROM_DATABASE=zte corporation
@@ -55208,6 +55838,9 @@ OUI:645A04*
OUI:645AED*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:645D86*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:645D92*
ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD
@@ -55226,6 +55859,9 @@ OUI:646184*
OUI:646223*
ID_OUI_FROM_DATABASE=Cellient Co., Ltd.
+OUI:64628A*
+ ID_OUI_FROM_DATABASE=evon GmbH
+
OUI:64649B*
ID_OUI_FROM_DATABASE=Juniper Networks
@@ -55253,6 +55889,9 @@ OUI:646A74*
OUI:646CB2*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:646D6C*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:646E69*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -55751,6 +56390,12 @@ OUI:683EEC*
OUI:684352*
ID_OUI_FROM_DATABASE=Bhuu Limited
+OUI:6843D7*
+ ID_OUI_FROM_DATABASE=Agilecom Photonics Solutions Guangdong Limited
+
+OUI:684749*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:684898*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -55833,7 +56478,7 @@ OUI:6872DC*
ID_OUI_FROM_DATABASE=CETORY.TV Company Limited
OUI:68764F*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:687848*
ID_OUI_FROM_DATABASE=Westunitis Co., Ltd.
@@ -56006,6 +56651,9 @@ OUI:68A828*
OUI:68A86D*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:68A8E1*
+ ID_OUI_FROM_DATABASE=Wacom Co.,Ltd.
+
OUI:68AAD2*
ID_OUI_FROM_DATABASE=DATECS LTD.,
@@ -56108,6 +56756,9 @@ OUI:68DBCA*
OUI:68DCE8*
ID_OUI_FROM_DATABASE=PacketStorm Communications
+OUI:68DD26*
+ ID_OUI_FROM_DATABASE=Shanghai Focus Vision Security Technology Co.,Ltd
+
OUI:68DFDD*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
@@ -56202,7 +56853,7 @@ OUI:6C0B84*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
OUI:6C0E0D*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:6C0EE6*
ID_OUI_FROM_DATABASE=Chengdu Xiyida Electronic Technology Co,.Ltd
@@ -56244,7 +56895,7 @@ OUI:6C22AB*
ID_OUI_FROM_DATABASE=Ainsworth Game Technology
OUI:6C23B9*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:6C2483*
ID_OUI_FROM_DATABASE=Microsoft Mobile Oy
@@ -56393,6 +57044,9 @@ OUI:6C626D*
OUI:6C641A*
ID_OUI_FROM_DATABASE=Penguin Computing
+OUI:6C6CD3*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:6C6EFE*
ID_OUI_FROM_DATABASE=Core Logic Inc.
@@ -56594,6 +57248,9 @@ OUI:6CC217*
OUI:6CC26B*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:6CC374*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:6CC4D5*
ID_OUI_FROM_DATABASE=HMD Global Oy
@@ -56654,6 +57311,9 @@ OUI:6CECA1*
OUI:6CECEB*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:6CED51*
+ ID_OUI_FROM_DATABASE=NEXCONTROL Co.,Ltd
+
OUI:6CEFC6*
ID_OUI_FROM_DATABASE=SHENZHEN TWOWING TECHNOLOGIES CO.,LTD.
@@ -56673,7 +57333,7 @@ OUI:6CF97C*
ID_OUI_FROM_DATABASE=Nanoptix Inc.
OUI:6CF9D2*
- ID_OUI_FROM_DATABASE=Chengdu Goods for the Road Electronic Technology C
+ ID_OUI_FROM_DATABASE=CHENGDU POVODO ELECTRONIC TECHNOLOGY CO., LTD
OUI:6CFA58*
ID_OUI_FROM_DATABASE=Avaya Inc
@@ -56699,12 +57359,18 @@ OUI:7001B5*
OUI:700258*
ID_OUI_FROM_DATABASE=01DB-METRAVIB
+OUI:70037E*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
OUI:700514*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
OUI:7006AC*
ID_OUI_FROM_DATABASE=Eastcompeace Technology Co., Ltd
+OUI:700B01*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:700BC0*
ID_OUI_FROM_DATABASE=Dewav Technology Company
@@ -56786,6 +57452,9 @@ OUI:702900*
OUI:702A7D*
ID_OUI_FROM_DATABASE=EpSpot AB
+OUI:702AD5*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:702B1D*
ID_OUI_FROM_DATABASE=E-Domus International Limited
@@ -56888,9 +57557,15 @@ OUI:704E01*
OUI:704E66*
ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD
+OUI:704F08*
+ ID_OUI_FROM_DATABASE=Shenzhen Huisheng Information Technology Co., Ltd.
+
OUI:704F57*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:704FB8*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:7050AF*
ID_OUI_FROM_DATABASE=BSkyB Ltd
@@ -57251,6 +57926,9 @@ OUI:70B3D5011*
OUI:70B3D5012*
ID_OUI_FROM_DATABASE=KST technology
+OUI:70B3D5014*
+ ID_OUI_FROM_DATABASE=FRAKO Kondensatoren und Anlagenbau GmbH
+
OUI:70B3D5015*
ID_OUI_FROM_DATABASE=EN ElectronicNetwork Hamburg GmbH
@@ -57305,6 +57983,9 @@ OUI:70B3D502D*
OUI:70B3D502E*
ID_OUI_FROM_DATABASE=Monnit Corporation
+OUI:70B3D502F*
+ ID_OUI_FROM_DATABASE=LEGENDAIRE TECHNOLOGY CO., LTD.
+
OUI:70B3D5030*
ID_OUI_FROM_DATABASE=Tresent Technologies
@@ -57371,6 +58052,9 @@ OUI:70B3D504D*
OUI:70B3D504E*
ID_OUI_FROM_DATABASE=HUGEL GmbH
+OUI:70B3D5050*
+ ID_OUI_FROM_DATABASE=Compusign Systems Pty Ltd
+
OUI:70B3D5052*
ID_OUI_FROM_DATABASE=Sudo Premium Engineering
@@ -57416,9 +58100,15 @@ OUI:70B3D506B*
OUI:70B3D506C*
ID_OUI_FROM_DATABASE=AppTek
+OUI:70B3D506F*
+ ID_OUI_FROM_DATABASE=Beijing Daswell Science and Technology Co.LTD
+
OUI:70B3D5070*
ID_OUI_FROM_DATABASE=Lumiplan Duhamel
+OUI:70B3D5073*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
OUI:70B3D5075*
ID_OUI_FROM_DATABASE=Mo-Sys Engineering Ltd
@@ -57434,6 +58124,9 @@ OUI:70B3D5079*
OUI:70B3D507A*
ID_OUI_FROM_DATABASE=ZAO ZEO
+OUI:70B3D507B*
+ ID_OUI_FROM_DATABASE=wallbe GmbH
+
OUI:70B3D507D*
ID_OUI_FROM_DATABASE=PANORAMIC POWER
@@ -57449,6 +58142,9 @@ OUI:70B3D5081*
OUI:70B3D5083*
ID_OUI_FROM_DATABASE=ZAO ZEO
+OUI:70B3D5084*
+ ID_OUI_FROM_DATABASE=Rako Controls Ltd
+
OUI:70B3D5085*
ID_OUI_FROM_DATABASE=Human Systems Integration
@@ -57494,6 +58190,9 @@ OUI:70B3D5097*
OUI:70B3D5099*
ID_OUI_FROM_DATABASE=Schwer+Kopka GmbH
+OUI:70B3D509A*
+ ID_OUI_FROM_DATABASE=Akse srl
+
OUI:70B3D509B*
ID_OUI_FROM_DATABASE=Jacarta Ltd
@@ -57527,6 +58226,9 @@ OUI:70B3D50A5*
OUI:70B3D50A6*
ID_OUI_FROM_DATABASE=PA CONSULTING SERVICES
+OUI:70B3D50A8*
+ ID_OUI_FROM_DATABASE=Symetrics Industries d.b.a. Extant Aerospace
+
OUI:70B3D50A9*
ID_OUI_FROM_DATABASE=ProConnections, Inc.
@@ -57578,6 +58280,9 @@ OUI:70B3D50BD*
OUI:70B3D50BE*
ID_OUI_FROM_DATABASE=ChamSys Ltd
+OUI:70B3D50BF*
+ ID_OUI_FROM_DATABASE=Den Automation
+
OUI:70B3D50C0*
ID_OUI_FROM_DATABASE=Molu Technology Inc., LTD.
@@ -57599,6 +58304,9 @@ OUI:70B3D50C6*
OUI:70B3D50C8*
ID_OUI_FROM_DATABASE=Fin Robotics Inc
+OUI:70B3D50C9*
+ ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD.,
+
OUI:70B3D50CD*
ID_OUI_FROM_DATABASE=AML Oceanographic
@@ -57644,6 +58352,9 @@ OUI:70B3D50DF*
OUI:70B3D50E0*
ID_OUI_FROM_DATABASE=PLCiS
+OUI:70B3D50E1*
+ ID_OUI_FROM_DATABASE=MiWave Consulting, LLC
+
OUI:70B3D50E3*
ID_OUI_FROM_DATABASE=SinTau SrL
@@ -57674,6 +58385,9 @@ OUI:70B3D50F1*
OUI:70B3D50F3*
ID_OUI_FROM_DATABASE=MonsoonRF, Inc.
+OUI:70B3D50F7*
+ ID_OUI_FROM_DATABASE=Bespoon
+
OUI:70B3D50F8*
ID_OUI_FROM_DATABASE=Special Services Group, LLC
@@ -57701,6 +58415,9 @@ OUI:70B3D5103*
OUI:70B3D5104*
ID_OUI_FROM_DATABASE=Plum sp. z o.o
+OUI:70B3D5105*
+ ID_OUI_FROM_DATABASE=Beijing Nacao Technology Co., Ltd.
+
OUI:70B3D5106*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
@@ -57734,6 +58451,9 @@ OUI:70B3D5115*
OUI:70B3D5119*
ID_OUI_FROM_DATABASE=Private
+OUI:70B3D511B*
+ ID_OUI_FROM_DATABASE=HoseoTelnet Inc...
+
OUI:70B3D511C*
ID_OUI_FROM_DATABASE=Samriddi Automations Pvt. Ltd.
@@ -57749,6 +58469,9 @@ OUI:70B3D5120*
OUI:70B3D5122*
ID_OUI_FROM_DATABASE=Henri Systems Holland bv
+OUI:70B3D5123*
+ ID_OUI_FROM_DATABASE=Amfitech ApS
+
OUI:70B3D5124*
ID_OUI_FROM_DATABASE=Forschungs- und Transferzentrum Leipzig e.V.
@@ -57872,11 +58595,17 @@ OUI:70B3D515C*
OUI:70B3D515D*
ID_OUI_FROM_DATABASE=Vtron Pty Ltd
+OUI:70B3D515E*
+ ID_OUI_FROM_DATABASE=Season Electronics Ltd
+
OUI:70B3D515F*
ID_OUI_FROM_DATABASE=SAVRONİK ELEKTRONİK
OUI:70B3D5161*
- ID_OUI_FROM_DATABASE=MB Connect Line GmbH
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+
+OUI:70B3D5162*
+ ID_OUI_FROM_DATABASE=ESPAI DE PRODUCCIÓ I ELECTRÓNI
OUI:70B3D5163*
ID_OUI_FROM_DATABASE=BHARAT HEAVY ELECTRICALS LIMITED
@@ -57939,7 +58668,7 @@ OUI:70B3D517E*
ID_OUI_FROM_DATABASE=OCULI VISION
OUI:70B3D517F*
- ID_OUI_FROM_DATABASE=MB Connect Line GmbH
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
OUI:70B3D5180*
ID_OUI_FROM_DATABASE=LHA Systems (Pty) Ltd
@@ -58073,6 +58802,9 @@ OUI:70B3D51C8*
OUI:70B3D51CB*
ID_OUI_FROM_DATABASE=MatchX GmbH
+OUI:70B3D51CC*
+ ID_OUI_FROM_DATABASE=AooGee Controls Co., LTD.
+
OUI:70B3D51CD*
ID_OUI_FROM_DATABASE=ELEUSI GmbH
@@ -58133,6 +58865,9 @@ OUI:70B3D51F4*
OUI:70B3D51F5*
ID_OUI_FROM_DATABASE=Martec S.p.A.
+OUI:70B3D51F8*
+ ID_OUI_FROM_DATABASE=Convergent Design
+
OUI:70B3D51FD*
ID_OUI_FROM_DATABASE=BRS Sistemas Eletrônicos
@@ -58208,6 +58943,9 @@ OUI:70B3D521D*
OUI:70B3D521E*
ID_OUI_FROM_DATABASE=Hildebrand Technology Limited
+OUI:70B3D521F*
+ ID_OUI_FROM_DATABASE=CHRONOMEDIA
+
OUI:70B3D5220*
ID_OUI_FROM_DATABASE=Private
@@ -58217,6 +58955,9 @@ OUI:70B3D5222*
OUI:70B3D5224*
ID_OUI_FROM_DATABASE=Urbana Smart Solutions Pte Ltd
+OUI:70B3D5225*
+ ID_OUI_FROM_DATABASE=RCD Radiokomunikace
+
OUI:70B3D5226*
ID_OUI_FROM_DATABASE=Yaviar
@@ -58250,6 +58991,9 @@ OUI:70B3D5231*
OUI:70B3D5232*
ID_OUI_FROM_DATABASE=UCONSYS
+OUI:70B3D5235*
+ ID_OUI_FROM_DATABASE=CAMEON S.A.
+
OUI:70B3D5236*
ID_OUI_FROM_DATABASE=Monnit Corporation
@@ -58268,6 +59012,12 @@ OUI:70B3D523C*
OUI:70B3D523E*
ID_OUI_FROM_DATABASE=Tornado Modular Systems
+OUI:70B3D523F*
+ ID_OUI_FROM_DATABASE=ETA-USA
+
+OUI:70B3D5240*
+ ID_OUI_FROM_DATABASE=Orlaco Products B.V.
+
OUI:70B3D5241*
ID_OUI_FROM_DATABASE=Bolide Technology Group, Inc.
@@ -58280,6 +59030,9 @@ OUI:70B3D5245*
OUI:70B3D5246*
ID_OUI_FROM_DATABASE=Saline Lectronics, Inc.
+OUI:70B3D5248*
+ ID_OUI_FROM_DATABASE=GL TECH CO.,LTD
+
OUI:70B3D524B*
ID_OUI_FROM_DATABASE=TOSEI ENGINEERING CORP.
@@ -58343,6 +59096,9 @@ OUI:70B3D5269*
OUI:70B3D526B*
ID_OUI_FROM_DATABASE=Sorama BV
+OUI:70B3D526C*
+ ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG
+
OUI:70B3D526E*
ID_OUI_FROM_DATABASE=HI-TECH SYSTEM Co. Ltd.
@@ -58379,6 +59135,9 @@ OUI:70B3D527E*
OUI:70B3D527F*
ID_OUI_FROM_DATABASE=ST Aerospace Systems
+OUI:70B3D5280*
+ ID_OUI_FROM_DATABASE=Computech International
+
OUI:70B3D5283*
ID_OUI_FROM_DATABASE=TextNinja Co.
@@ -58445,6 +59204,9 @@ OUI:70B3D52A1*
OUI:70B3D52A2*
ID_OUI_FROM_DATABASE=Visualware, Inc.
+OUI:70B3D52A3*
+ ID_OUI_FROM_DATABASE=ATT Nussbaum Prüftechnik GmbH
+
OUI:70B3D52A4*
ID_OUI_FROM_DATABASE=GSP Sprachtechnologie GmbH
@@ -58478,6 +59240,9 @@ OUI:70B3D52B0*
OUI:70B3D52B1*
ID_OUI_FROM_DATABASE=WIXCON Co., Ltd
+OUI:70B3D52B2*
+ ID_OUI_FROM_DATABASE=Sun Creative (ZheJiang) Technology INC.
+
OUI:70B3D52B3*
ID_OUI_FROM_DATABASE=HAS co.,ltd.
@@ -58530,7 +59295,7 @@ OUI:70B3D52CE*
ID_OUI_FROM_DATABASE=KDT
OUI:70B3D52CF*
- ID_OUI_FROM_DATABASE=MB Connect Line GmbH
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
OUI:70B3D52D0*
ID_OUI_FROM_DATABASE=ijin co.,ltd.
@@ -58658,6 +59423,9 @@ OUI:70B3D5317*
OUI:70B3D5319*
ID_OUI_FROM_DATABASE=ISO/TC 22/SC 31
+OUI:70B3D531B*
+ ID_OUI_FROM_DATABASE=SilTerra Malaysia Sdn. Bhd.
+
OUI:70B3D531C*
ID_OUI_FROM_DATABASE=FINANCIERE DE L'OMBREE (eolane)
@@ -58685,6 +59453,9 @@ OUI:70B3D5328*
OUI:70B3D532A*
ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd
+OUI:70B3D532D*
+ ID_OUI_FROM_DATABASE=Hanwell Technology Co., Ltd.
+
OUI:70B3D532F*
ID_OUI_FROM_DATABASE=Movidius SRL
@@ -58775,6 +59546,9 @@ OUI:70B3D535E*
OUI:70B3D535F*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+OUI:70B3D5360*
+ ID_OUI_FROM_DATABASE=PT. Emsonic Indonesia
+
OUI:70B3D5361*
ID_OUI_FROM_DATABASE=Parent Power
@@ -58922,6 +59696,9 @@ OUI:70B3D53AE*
OUI:70B3D53AF*
ID_OUI_FROM_DATABASE=Turbo Technologies Corporation
+OUI:70B3D53B0*
+ ID_OUI_FROM_DATABASE=Millennial Net, Inc.
+
OUI:70B3D53B2*
ID_OUI_FROM_DATABASE=Sicon srl
@@ -58958,12 +59735,18 @@ OUI:70B3D53C2*
OUI:70B3D53C3*
ID_OUI_FROM_DATABASE=AIMCO
+OUI:70B3D53C4*
+ ID_OUI_FROM_DATABASE=Hagiwara Solutions Co., Ltd.
+
OUI:70B3D53C5*
ID_OUI_FROM_DATABASE=P4Q ELECTRONICS, S.L.
OUI:70B3D53C6*
ID_OUI_FROM_DATABASE=ACD Elekronik GmbH
+OUI:70B3D53C7*
+ ID_OUI_FROM_DATABASE=SOFTCREATE CORP.
+
OUI:70B3D53C9*
ID_OUI_FROM_DATABASE=Duerkopp-Adler
@@ -59021,6 +59804,9 @@ OUI:70B3D53E4*
OUI:70B3D53E5*
ID_OUI_FROM_DATABASE=ATEME
+OUI:70B3D53E6*
+ ID_OUI_FROM_DATABASE=machineQ
+
OUI:70B3D53E8*
ID_OUI_FROM_DATABASE=COSMOS web Co., Ltd.
@@ -59039,15 +59825,24 @@ OUI:70B3D53F0*
OUI:70B3D53F1*
ID_OUI_FROM_DATABASE=Olympus NDT Canada
+OUI:70B3D53F2*
+ ID_OUI_FROM_DATABASE=H3D, Inc.
+
OUI:70B3D53F3*
ID_OUI_FROM_DATABASE=SPEA SPA
OUI:70B3D53F4*
ID_OUI_FROM_DATABASE=Wincode Technology Co., Ltd.
+OUI:70B3D53F5*
+ ID_OUI_FROM_DATABASE=DOLBY LABORATORIES, INC.
+
OUI:70B3D53F6*
ID_OUI_FROM_DATABASE=Sycomp Electronic GmbH
+OUI:70B3D53F7*
+ ID_OUI_FROM_DATABASE=Advansid
+
OUI:70B3D53F9*
ID_OUI_FROM_DATABASE=Herrick Tech Labs
@@ -59060,12 +59855,18 @@ OUI:70B3D53FF*
OUI:70B3D5400*
ID_OUI_FROM_DATABASE=Vtron Pty Ltd
+OUI:70B3D5401*
+ ID_OUI_FROM_DATABASE=Private
+
OUI:70B3D5404*
ID_OUI_FROM_DATABASE=RANIX,Inc.
OUI:70B3D5405*
ID_OUI_FROM_DATABASE=MG s.r.l.
+OUI:70B3D5406*
+ ID_OUI_FROM_DATABASE=Acrodea, Inc.
+
OUI:70B3D5407*
ID_OUI_FROM_DATABASE=IDOSENS
@@ -59084,6 +59885,9 @@ OUI:70B3D5412*
OUI:70B3D5413*
ID_OUI_FROM_DATABASE=Axess AG
+OUI:70B3D5415*
+ ID_OUI_FROM_DATABASE=IDEA SPA
+
OUI:70B3D5417*
ID_OUI_FROM_DATABASE=Figment Design Laboratories
@@ -59135,6 +59939,9 @@ OUI:70B3D5432*
OUI:70B3D5433*
ID_OUI_FROM_DATABASE=Flexsolution APS
+OUI:70B3D5434*
+ ID_OUI_FROM_DATABASE=Wit.com Inc
+
OUI:70B3D5435*
ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd
@@ -59195,6 +60002,9 @@ OUI:70B3D545E*
OUI:70B3D545F*
ID_OUI_FROM_DATABASE=Cloud4Wi
+OUI:70B3D5460*
+ ID_OUI_FROM_DATABASE=Guilin Tryin Technology Co.,Ltd
+
OUI:70B3D5461*
ID_OUI_FROM_DATABASE=TESEC Corporation
@@ -59219,6 +60029,9 @@ OUI:70B3D546F*
OUI:70B3D5470*
ID_OUI_FROM_DATABASE=KITRON UAB
+OUI:70B3D5471*
+ ID_OUI_FROM_DATABASE=SYSCO Sicherheitssysteme GmbH
+
OUI:70B3D5472*
ID_OUI_FROM_DATABASE=Quadio Devices Private Limited
@@ -59495,6 +60308,9 @@ OUI:70B3D5511*
OUI:70B3D5513*
ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+OUI:70B3D5515*
+ ID_OUI_FROM_DATABASE=PCSC
+
OUI:70B3D5517*
ID_OUI_FROM_DATABASE=ISPHER
@@ -59558,12 +60374,21 @@ OUI:70B3D553A*
OUI:70B3D553B*
ID_OUI_FROM_DATABASE=Mr.Loop
+OUI:70B3D553C*
+ ID_OUI_FROM_DATABASE=Airthings
+
+OUI:70B3D553D*
+ ID_OUI_FROM_DATABASE=ACCEL CORP
+
OUI:70B3D5542*
ID_OUI_FROM_DATABASE=RTDS Technologies Inc.
OUI:70B3D5544*
ID_OUI_FROM_DATABASE=Silicon Safe Ltd
+OUI:70B3D5546*
+ ID_OUI_FROM_DATABASE=Sensefarm AB
+
OUI:70B3D5547*
ID_OUI_FROM_DATABASE=CE LINK LIMITED
@@ -59630,6 +60455,9 @@ OUI:70B3D5564*
OUI:70B3D5566*
ID_OUI_FROM_DATABASE=Data Informs LLC
+OUI:70B3D556A*
+ ID_OUI_FROM_DATABASE=Harvard Technology Ltd
+
OUI:70B3D556B*
ID_OUI_FROM_DATABASE=S.E.I. CO.,LTD.
@@ -59786,6 +60614,9 @@ OUI:70B3D55CC*
OUI:70B3D55CD*
ID_OUI_FROM_DATABASE=MVT Video Technologies R + H Maedler GbR
+OUI:70B3D55CF*
+ ID_OUI_FROM_DATABASE=PROEL TSI s.r.l.
+
OUI:70B3D55D1*
ID_OUI_FROM_DATABASE=Software Motor Corp
@@ -59855,6 +60686,9 @@ OUI:70B3D55F0*
OUI:70B3D55F1*
ID_OUI_FROM_DATABASE=Fater Rasa Noor
+OUI:70B3D55F2*
+ ID_OUI_FROM_DATABASE=Invisible Systems Limited
+
OUI:70B3D55F3*
ID_OUI_FROM_DATABASE=Rtone
@@ -59864,6 +60698,12 @@ OUI:70B3D55F4*
OUI:70B3D55F6*
ID_OUI_FROM_DATABASE=FreeFlight Systems
+OUI:70B3D55F9*
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+
+OUI:70B3D55FA*
+ ID_OUI_FROM_DATABASE=TEX COMPUTER SRL
+
OUI:70B3D55FB*
ID_OUI_FROM_DATABASE=TELEPLATFORMS
@@ -59942,6 +60782,9 @@ OUI:70B3D561C*
OUI:70B3D561D*
ID_OUI_FROM_DATABASE=Telonic Berkeley Inc
+OUI:70B3D561E*
+ ID_OUI_FROM_DATABASE=PKE Electronics AG
+
OUI:70B3D561F*
ID_OUI_FROM_DATABASE=Labotect Labor-Technik-Göttingen GmbH
@@ -59966,6 +60809,9 @@ OUI:70B3D5634*
OUI:70B3D5635*
ID_OUI_FROM_DATABASE=Cosylab d.d.
+OUI:70B3D5636*
+ ID_OUI_FROM_DATABASE=Globalcom Engineering SPA
+
OUI:70B3D5637*
ID_OUI_FROM_DATABASE=INEO-SENSE
@@ -60071,6 +60917,9 @@ OUI:70B3D5665*
OUI:70B3D5666*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+OUI:70B3D566A*
+ ID_OUI_FROM_DATABASE=Private
+
OUI:70B3D566B*
ID_OUI_FROM_DATABASE=Innitive B.V.
@@ -60086,6 +60935,9 @@ OUI:70B3D5672*
OUI:70B3D5674*
ID_OUI_FROM_DATABASE=Fortress Cyber Security
+OUI:70B3D5675*
+ ID_OUI_FROM_DATABASE=alfamation spa
+
OUI:70B3D5676*
ID_OUI_FROM_DATABASE=samwooeleco
@@ -60101,6 +60953,12 @@ OUI:70B3D5679*
OUI:70B3D567B*
ID_OUI_FROM_DATABASE=Stesalit Systems Ltd
+OUI:70B3D567D*
+ ID_OUI_FROM_DATABASE=Acrodea, Inc.
+
+OUI:70B3D5680*
+ ID_OUI_FROM_DATABASE=BASF Corporation
+
OUI:70B3D5682*
ID_OUI_FROM_DATABASE=Rosslare Enterprises Limited
@@ -60134,6 +60992,9 @@ OUI:70B3D5696*
OUI:70B3D5697*
ID_OUI_FROM_DATABASE=Alazar Technologies Inc.
+OUI:70B3D569C*
+ ID_OUI_FROM_DATABASE=Keepen
+
OUI:70B3D569E*
ID_OUI_FROM_DATABASE=PTYPE Co., LTD.
@@ -60197,6 +61058,9 @@ OUI:70B3D56BF*
OUI:70B3D56C1*
ID_OUI_FROM_DATABASE=Labtronik s.r.l.
+OUI:70B3D56C3*
+ ID_OUI_FROM_DATABASE=BEIJING ZGH SECURITY RESEARCH INSTITUTE CO., LTD
+
OUI:70B3D56C5*
ID_OUI_FROM_DATABASE=CJSC «Russian telecom equipment company» (CJSC RTEC)
@@ -60281,6 +61145,9 @@ OUI:70B3D56F3*
OUI:70B3D56F6*
ID_OUI_FROM_DATABASE=Acco Brands Europe
+OUI:70B3D56F7*
+ ID_OUI_FROM_DATABASE=EGICON SRL
+
OUI:70B3D56F8*
ID_OUI_FROM_DATABASE=SENSEON Corporation
@@ -60314,6 +61181,12 @@ OUI:70B3D5704*
OUI:70B3D5705*
ID_OUI_FROM_DATABASE=Digital Matter Pty Ltd
+OUI:70B3D5706*
+ ID_OUI_FROM_DATABASE=Smith Meter, Inc.
+
+OUI:70B3D5707*
+ ID_OUI_FROM_DATABASE=Koco Motion US LLC
+
OUI:70B3D5708*
ID_OUI_FROM_DATABASE=IBM Research GmbH
@@ -60470,6 +61343,9 @@ OUI:70B3D5753*
OUI:70B3D5755*
ID_OUI_FROM_DATABASE=LandmarkTech Systems Technology Co.,Ltd.
+OUI:70B3D5758*
+ ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG
+
OUI:70B3D575A*
ID_OUI_FROM_DATABASE=Standard Backhaul Communications
@@ -60497,6 +61373,9 @@ OUI:70B3D5761*
OUI:70B3D5763*
ID_OUI_FROM_DATABASE=A Trap, USA
+OUI:70B3D5764*
+ ID_OUI_FROM_DATABASE=SCHMID electronic
+
OUI:70B3D5766*
ID_OUI_FROM_DATABASE=Tirasoft Nederland
@@ -60521,6 +61400,9 @@ OUI:70B3D576E*
OUI:70B3D576F*
ID_OUI_FROM_DATABASE=OTI LTD
+OUI:70B3D5770*
+ ID_OUI_FROM_DATABASE=STREGA
+
OUI:70B3D5771*
ID_OUI_FROM_DATABASE=Apator Miitors ApS
@@ -60584,6 +61466,9 @@ OUI:70B3D578C*
OUI:70B3D578E*
ID_OUI_FROM_DATABASE=effectas GmbH
+OUI:70B3D578F*
+ ID_OUI_FROM_DATABASE=SoFiHa
+
OUI:70B3D5790*
ID_OUI_FROM_DATABASE=AVI Pty Ltd
@@ -60695,6 +61580,9 @@ OUI:70B3D57C2*
OUI:70B3D57C3*
ID_OUI_FROM_DATABASE=Flexim Security Oy
+OUI:70B3D57C7*
+ ID_OUI_FROM_DATABASE=Sicon srl
+
OUI:70B3D57C8*
ID_OUI_FROM_DATABASE=CRDE
@@ -60779,6 +61667,9 @@ OUI:70B3D57EC*
OUI:70B3D57ED*
ID_OUI_FROM_DATABASE=The Things Network Foundation
+OUI:70B3D57EE*
+ ID_OUI_FROM_DATABASE=ADVEEZ
+
OUI:70B3D57EF*
ID_OUI_FROM_DATABASE=CRAVIS CO., LIMITED
@@ -60794,6 +61685,9 @@ OUI:70B3D57F3*
OUI:70B3D57F4*
ID_OUI_FROM_DATABASE=KST technology
+OUI:70B3D57F5*
+ ID_OUI_FROM_DATABASE=Incusense
+
OUI:70B3D57F7*
ID_OUI_FROM_DATABASE=JASCO Applied Sciences Canada Ltd
@@ -60893,6 +61787,9 @@ OUI:70B3D5828*
OUI:70B3D582C*
ID_OUI_FROM_DATABASE=NELS Ltd.
+OUI:70B3D582D*
+ ID_OUI_FROM_DATABASE=Elektronik Art S.C.
+
OUI:70B3D582E*
ID_OUI_FROM_DATABASE=PlayAlive A/S
@@ -60941,12 +61838,18 @@ OUI:70B3D5845*
OUI:70B3D5847*
ID_OUI_FROM_DATABASE=Ai-Lynx
+OUI:70B3D5848*
+ ID_OUI_FROM_DATABASE=Aldridge Electrical Industries
+
OUI:70B3D5849*
ID_OUI_FROM_DATABASE=RF-Tuote Oy
OUI:70B3D584A*
ID_OUI_FROM_DATABASE=MOG Laboratories Pty Ltd
+OUI:70B3D584C*
+ ID_OUI_FROM_DATABASE=CoreKinect
+
OUI:70B3D584D*
ID_OUI_FROM_DATABASE=Quantum Design Inc.
@@ -60968,6 +61871,9 @@ OUI:70B3D5854*
OUI:70B3D5855*
ID_OUI_FROM_DATABASE=CRDE
+OUI:70B3D5857*
+ ID_OUI_FROM_DATABASE=RCH Italia SpA
+
OUI:70B3D585A*
ID_OUI_FROM_DATABASE=BRUSHIES
@@ -60983,12 +61889,21 @@ OUI:70B3D585D*
OUI:70B3D585E*
ID_OUI_FROM_DATABASE=XLOGIC srl
+OUI:70B3D585F*
+ ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd
+
OUI:70B3D5861*
ID_OUI_FROM_DATABASE=KST technology
+OUI:70B3D5862*
+ ID_OUI_FROM_DATABASE=TripleOre
+
OUI:70B3D5866*
ID_OUI_FROM_DATABASE=MEPS Realtime
+OUI:70B3D5868*
+ ID_OUI_FROM_DATABASE=U-JIN Mesco Co., Ltd.
+
OUI:70B3D586C*
ID_OUI_FROM_DATABASE=eeas gmbh
@@ -61010,6 +61925,9 @@ OUI:70B3D5873*
OUI:70B3D5875*
ID_OUI_FROM_DATABASE=Peek Traffic
+OUI:70B3D5876*
+ ID_OUI_FROM_DATABASE=IONETECH
+
OUI:70B3D5877*
ID_OUI_FROM_DATABASE=Polynet Telecommunications Consulting and Contractor Ltd.
@@ -61025,6 +61943,9 @@ OUI:70B3D587B*
OUI:70B3D587C*
ID_OUI_FROM_DATABASE=Nautel Limited
+OUI:70B3D587D*
+ ID_OUI_FROM_DATABASE=INVIXIUM ACCESS INC.
+
OUI:70B3D587E*
ID_OUI_FROM_DATABASE=Septentrio NV
@@ -61085,9 +62006,15 @@ OUI:70B3D589B*
OUI:70B3D58A0*
ID_OUI_FROM_DATABASE=DM RADIOCOM
+OUI:70B3D58A2*
+ ID_OUI_FROM_DATABASE=WINNERS DIGITAL CORPORATION
+
OUI:70B3D58A4*
ID_OUI_FROM_DATABASE=Phyton, Inc. Microsystems and Development Tools
+OUI:70B3D58A5*
+ ID_OUI_FROM_DATABASE=KST technology
+
OUI:70B3D58A6*
ID_OUI_FROM_DATABASE=CRDE
@@ -61139,6 +62066,9 @@ OUI:70B3D58C3*
OUI:70B3D58C5*
ID_OUI_FROM_DATABASE=HMicro Inc
+OUI:70B3D58C6*
+ ID_OUI_FROM_DATABASE=Onosokki Co.,Ltd
+
OUI:70B3D58C8*
ID_OUI_FROM_DATABASE=KRONOTECH SRL
@@ -61184,6 +62114,9 @@ OUI:70B3D58E3*
OUI:70B3D58E4*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+OUI:70B3D58EB*
+ ID_OUI_FROM_DATABASE=Procon Electronics Pty Ltd
+
OUI:70B3D58EC*
ID_OUI_FROM_DATABASE=Rudy Tellert
@@ -61235,6 +62168,9 @@ OUI:70B3D5904*
OUI:70B3D5906*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+OUI:70B3D5907*
+ ID_OUI_FROM_DATABASE=NINGBO CRRC TIMES TRANSDUCER TECHNOLOGY CO., LTD
+
OUI:70B3D5908*
ID_OUI_FROM_DATABASE=Accusonic
@@ -61310,6 +62246,9 @@ OUI:70B3D592A*
OUI:70B3D592B*
ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD.
+OUI:70B3D592E*
+ ID_OUI_FROM_DATABASE=Medical Monitoring Center OOD
+
OUI:70B3D592F*
ID_OUI_FROM_DATABASE=SiFive
@@ -61358,6 +62297,9 @@ OUI:70B3D5945*
OUI:70B3D5947*
ID_OUI_FROM_DATABASE=Checkbill Co,Ltd.
+OUI:70B3D5948*
+ ID_OUI_FROM_DATABASE=VISION SYSTEMS AURTOMOTIVE (SAFETY TECH)
+
OUI:70B3D594A*
ID_OUI_FROM_DATABASE=SHENZHEN WISEWING INTERNET TECHNOLOGY CO.,LTD
@@ -61367,6 +62309,9 @@ OUI:70B3D594D*
OUI:70B3D594F*
ID_OUI_FROM_DATABASE=MART NETWORK SOLUTIONS LTD
+OUI:70B3D5950*
+ ID_OUI_FROM_DATABASE=CMT Medical technologies
+
OUI:70B3D5952*
ID_OUI_FROM_DATABASE=REQUEA
@@ -61403,6 +62348,12 @@ OUI:70B3D595C*
OUI:70B3D595E*
ID_OUI_FROM_DATABASE=BLOCKSI LLC
+OUI:70B3D5960*
+ ID_OUI_FROM_DATABASE=HORIZON TELECOM
+
+OUI:70B3D5961*
+ ID_OUI_FROM_DATABASE=TASK SISTEMAS DE COMPUTACAO LTDA
+
OUI:70B3D5963*
ID_OUI_FROM_DATABASE=Triax A/S
@@ -61448,6 +62399,9 @@ OUI:70B3D5981*
OUI:70B3D5984*
ID_OUI_FROM_DATABASE=Sanmina Israel
+OUI:70B3D5985*
+ ID_OUI_FROM_DATABASE=Burk Technology
+
OUI:70B3D5986*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
@@ -61511,6 +62465,12 @@ OUI:70B3D59A1*
OUI:70B3D59A7*
ID_OUI_FROM_DATABASE=Honeywell
+OUI:70B3D59AA*
+ ID_OUI_FROM_DATABASE=Tecsys do Brasil Industrial Ltda
+
+OUI:70B3D59AB*
+ ID_OUI_FROM_DATABASE=Groupe Paris-Turf
+
OUI:70B3D59AD*
ID_OUI_FROM_DATABASE=Fortuna Impex Pvt ltd
@@ -61526,6 +62486,9 @@ OUI:70B3D59B2*
OUI:70B3D59B3*
ID_OUI_FROM_DATABASE=K&J Schmittschneider AG
+OUI:70B3D59B4*
+ ID_OUI_FROM_DATABASE=MyoungSung System
+
OUI:70B3D59B5*
ID_OUI_FROM_DATABASE=Ideetron b.v.
@@ -61571,6 +62534,9 @@ OUI:70B3D59CE*
OUI:70B3D59D0*
ID_OUI_FROM_DATABASE=RJ45 Technologies
+OUI:70B3D59D1*
+ ID_OUI_FROM_DATABASE=OS42 UG (haftungsbeschraenkt)
+
OUI:70B3D59D2*
ID_OUI_FROM_DATABASE=ACS MOTION CONTROL
@@ -61607,6 +62573,9 @@ OUI:70B3D59E0*
OUI:70B3D59E2*
ID_OUI_FROM_DATABASE=Ofil USA
+OUI:70B3D59E3*
+ ID_OUI_FROM_DATABASE=LG Electronics
+
OUI:70B3D59E6*
ID_OUI_FROM_DATABASE=BLOCKSI LLC
@@ -61679,6 +62648,9 @@ OUI:70B3D5A07*
OUI:70B3D5A08*
ID_OUI_FROM_DATABASE=BioBusiness
+OUI:70B3D5A0A*
+ ID_OUI_FROM_DATABASE=CAPSYS
+
OUI:70B3D5A0B*
ID_OUI_FROM_DATABASE=ambiHome GmbH
@@ -61793,6 +62765,9 @@ OUI:70B3D5A43*
OUI:70B3D5A44*
ID_OUI_FROM_DATABASE=FSR Inc
+OUI:70B3D5A46*
+ ID_OUI_FROM_DATABASE=Foxconn 4Tech
+
OUI:70B3D5A47*
ID_OUI_FROM_DATABASE=KANOA INC
@@ -61823,6 +62798,9 @@ OUI:70B3D5A51*
OUI:70B3D5A53*
ID_OUI_FROM_DATABASE=GS Industrie-Elektronik GmbH
+OUI:70B3D5A54*
+ ID_OUI_FROM_DATABASE=provedo
+
OUI:70B3D5A55*
ID_OUI_FROM_DATABASE=Embest Technology Co., Ltd
@@ -61853,6 +62831,9 @@ OUI:70B3D5A5E*
OUI:70B3D5A62*
ID_OUI_FROM_DATABASE=Environexus
+OUI:70B3D5A64*
+ ID_OUI_FROM_DATABASE=Newshine
+
OUI:70B3D5A66*
ID_OUI_FROM_DATABASE=Trapeze Software Group Inc
@@ -61913,6 +62894,9 @@ OUI:70B3D5A89*
OUI:70B3D5A8B*
ID_OUI_FROM_DATABASE=Giant Power Technology Biomedical Corporation
+OUI:70B3D5A8D*
+ ID_OUI_FROM_DATABASE=Code Blue Corporation
+
OUI:70B3D5A8E*
ID_OUI_FROM_DATABASE=OMESH CITY GROUP
@@ -61928,6 +62912,9 @@ OUI:70B3D5A92*
OUI:70B3D5A93*
ID_OUI_FROM_DATABASE=Mes Communication Co., Ltd
+OUI:70B3D5A94*
+ ID_OUI_FROM_DATABASE=ETA Technology Pvt Ltd
+
OUI:70B3D5A95*
ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
@@ -61946,6 +62933,9 @@ OUI:70B3D5A9A*
OUI:70B3D5A9D*
ID_OUI_FROM_DATABASE=VITEC MULTIMEDIA
+OUI:70B3D5A9E*
+ ID_OUI_FROM_DATABASE=Argon ST
+
OUI:70B3D5A9F*
ID_OUI_FROM_DATABASE=Private
@@ -61955,6 +62945,9 @@ OUI:70B3D5AA0*
OUI:70B3D5AA1*
ID_OUI_FROM_DATABASE=Shenzhen Weema TV Technology Co.,Ltd.
+OUI:70B3D5AA2*
+ ID_OUI_FROM_DATABASE=eumig industrie-TV GmbH.
+
OUI:70B3D5AA3*
ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD.,
@@ -61988,6 +62981,9 @@ OUI:70B3D5AAF*
OUI:70B3D5AB0*
ID_OUI_FROM_DATABASE=OSR R&D ISRAEL LTD
+OUI:70B3D5AB3*
+ ID_OUI_FROM_DATABASE=MICAS AG
+
OUI:70B3D5AB4*
ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH
@@ -62021,6 +63017,9 @@ OUI:70B3D5AC1*
OUI:70B3D5AC3*
ID_OUI_FROM_DATABASE=Novoptel GmbH
+OUI:70B3D5AC4*
+ ID_OUI_FROM_DATABASE=Lexi Devices, Inc.
+
OUI:70B3D5AC5*
ID_OUI_FROM_DATABASE=ATOM GIKEN Co.,Ltd.
@@ -62036,6 +63035,9 @@ OUI:70B3D5AC8*
OUI:70B3D5AC9*
ID_OUI_FROM_DATABASE=Trinity Solutions LLC
+OUI:70B3D5ACB*
+ ID_OUI_FROM_DATABASE=TATTILE SRL
+
OUI:70B3D5ACD*
ID_OUI_FROM_DATABASE=CRDE
@@ -62159,6 +63161,9 @@ OUI:70B3D5B08*
OUI:70B3D5B09*
ID_OUI_FROM_DATABASE=FIRST LIGHT IMAGING
+OUI:70B3D5B0B*
+ ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL
+
OUI:70B3D5B0C*
ID_OUI_FROM_DATABASE=Vigilate srl
@@ -62186,6 +63191,12 @@ OUI:70B3D5B1A*
OUI:70B3D5B1D*
ID_OUI_FROM_DATABASE=Safelet BV
+OUI:70B3D5B1E*
+ ID_OUI_FROM_DATABASE=Fen Systems Ltd
+
+OUI:70B3D5B1F*
+ ID_OUI_FROM_DATABASE=TECNOWATT
+
OUI:70B3D5B21*
ID_OUI_FROM_DATABASE=TATTILE SRL
@@ -62232,7 +63243,7 @@ OUI:70B3D5B37*
ID_OUI_FROM_DATABASE=CODEC Co., Ltd.
OUI:70B3D5B39*
- ID_OUI_FROM_DATABASE=MB Connect Line GmbH
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
OUI:70B3D5B3A*
ID_OUI_FROM_DATABASE=Adigitalmedia
@@ -62267,6 +63278,9 @@ OUI:70B3D5B47*
OUI:70B3D5B48*
ID_OUI_FROM_DATABASE=DWQ Informatikai Tanacsado es Vezerlestechnikai KFT
+OUI:70B3D5B4A*
+ ID_OUI_FROM_DATABASE=MEDEX
+
OUI:70B3D5B51*
ID_OUI_FROM_DATABASE=Critical Link LLC
@@ -62366,6 +63380,9 @@ OUI:70B3D5B91*
OUI:70B3D5B93*
ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL
+OUI:70B3D5B94*
+ ID_OUI_FROM_DATABASE=Cygnetic Technologies (Pty) Ltd
+
OUI:70B3D5B97*
ID_OUI_FROM_DATABASE=Canam Technology, Inc.
@@ -62378,6 +63395,9 @@ OUI:70B3D5B99*
OUI:70B3D5B9B*
ID_OUI_FROM_DATABASE=Elektronik Art
+OUI:70B3D5B9C*
+ ID_OUI_FROM_DATABASE=EDCO Technology 1993 ltd
+
OUI:70B3D5B9E*
ID_OUI_FROM_DATABASE=POLSYSTEM SI SP. Z O.O., S.K.A.
@@ -62444,6 +63464,9 @@ OUI:70B3D5BBE*
OUI:70B3D5BBF*
ID_OUI_FROM_DATABASE=Ensys srl
+OUI:70B3D5BC1*
+ ID_OUI_FROM_DATABASE=Abionic
+
OUI:70B3D5BC2*
ID_OUI_FROM_DATABASE=DWEWOONG ELECTRIC Co., Ltd.
@@ -62453,6 +63476,9 @@ OUI:70B3D5BC6*
OUI:70B3D5BCA*
ID_OUI_FROM_DATABASE=Deymed Diagnostic
+OUI:70B3D5BCB*
+ ID_OUI_FROM_DATABASE=Smart Vision Lights
+
OUI:70B3D5BCC*
ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
@@ -62528,6 +63554,9 @@ OUI:70B3D5BF5*
OUI:70B3D5BF6*
ID_OUI_FROM_DATABASE=comtac AG
+OUI:70B3D5BF9*
+ ID_OUI_FROM_DATABASE=Okolab Srl
+
OUI:70B3D5BFA*
ID_OUI_FROM_DATABASE=NESA SRL
@@ -62543,6 +63572,9 @@ OUI:70B3D5C01*
OUI:70B3D5C03*
ID_OUI_FROM_DATABASE=XAVi Technologies Corp.
+OUI:70B3D5C05*
+ ID_OUI_FROM_DATABASE=KST technology
+
OUI:70B3D5C06*
ID_OUI_FROM_DATABASE=XotonicsMED GmbH
@@ -62552,6 +63584,9 @@ OUI:70B3D5C07*
OUI:70B3D5C0A*
ID_OUI_FROM_DATABASE=Infosocket Co., Ltd.
+OUI:70B3D5C0B*
+ ID_OUI_FROM_DATABASE=FSTUDIO CO LTD
+
OUI:70B3D5C0C*
ID_OUI_FROM_DATABASE=Tech4Race
@@ -62579,6 +63614,9 @@ OUI:70B3D5C16*
OUI:70B3D5C17*
ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC
+OUI:70B3D5C1A*
+ ID_OUI_FROM_DATABASE=Xylon
+
OUI:70B3D5C1B*
ID_OUI_FROM_DATABASE=Labinvent JSC
@@ -62630,9 +63668,15 @@ OUI:70B3D5C33*
OUI:70B3D5C34*
ID_OUI_FROM_DATABASE=Technical Panels Co. Ltd.
+OUI:70B3D5C35*
+ ID_OUI_FROM_DATABASE=Vibrationmaster
+
OUI:70B3D5C37*
ID_OUI_FROM_DATABASE=Keycom Corp.
+OUI:70B3D5C38*
+ ID_OUI_FROM_DATABASE=CRESPRIT INC.
+
OUI:70B3D5C39*
ID_OUI_FROM_DATABASE=MeshWorks Wireless Oy
@@ -62711,9 +63755,15 @@ OUI:70B3D5C62*
OUI:70B3D5C63*
ID_OUI_FROM_DATABASE=Xentech Solutions Limited
+OUI:70B3D5C64*
+ ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH
+
OUI:70B3D5C65*
ID_OUI_FROM_DATABASE=PEEK TRAFFIC
+OUI:70B3D5C66*
+ ID_OUI_FROM_DATABASE=Blue Access Inc
+
OUI:70B3D5C67*
ID_OUI_FROM_DATABASE=Collini Dienstleistungs GmbH
@@ -62750,6 +63800,9 @@ OUI:70B3D5C78*
OUI:70B3D5C79*
ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+OUI:70B3D5C7D*
+ ID_OUI_FROM_DATABASE=Metatronics B.V.
+
OUI:70B3D5C7E*
ID_OUI_FROM_DATABASE=BirdDog Australia
@@ -62807,6 +63860,9 @@ OUI:70B3D5C9B*
OUI:70B3D5C9D*
ID_OUI_FROM_DATABASE=APG Cash Drawer
+OUI:70B3D5C9E*
+ ID_OUI_FROM_DATABASE=FUKUDA SANGYO CO., LTD.
+
OUI:70B3D5C9F*
ID_OUI_FROM_DATABASE=Triax A/S
@@ -62894,6 +63950,9 @@ OUI:70B3D5CCE*
OUI:70B3D5CCF*
ID_OUI_FROM_DATABASE=Netberg
+OUI:70B3D5CD0*
+ ID_OUI_FROM_DATABASE=Ellenex Pty Ltd
+
OUI:70B3D5CD1*
ID_OUI_FROM_DATABASE=Cannex Technology Inc.
@@ -62918,9 +63977,15 @@ OUI:70B3D5CDA*
OUI:70B3D5CDE*
ID_OUI_FROM_DATABASE=Multipure International
+OUI:70B3D5CDF*
+ ID_OUI_FROM_DATABASE=3D Printing Specialists
+
OUI:70B3D5CE1*
ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG
+OUI:70B3D5CE2*
+ ID_OUI_FROM_DATABASE=Centero
+
OUI:70B3D5CE3*
ID_OUI_FROM_DATABASE=Dalcnet srl
@@ -63017,6 +64082,9 @@ OUI:70B3D5D20*
OUI:70B3D5D22*
ID_OUI_FROM_DATABASE=DEK Technologies
+OUI:70B3D5D24*
+ ID_OUI_FROM_DATABASE=Microtronics Engineering GmbH
+
OUI:70B3D5D25*
ID_OUI_FROM_DATABASE=ENGenesis
@@ -63032,6 +64100,9 @@ OUI:70B3D5D2B*
OUI:70B3D5D2D*
ID_OUI_FROM_DATABASE=Evolute Systems Private Limited
+OUI:70B3D5D2E*
+ ID_OUI_FROM_DATABASE=Coheros Oy
+
OUI:70B3D5D2F*
ID_OUI_FROM_DATABASE=L.I.F.E. Corporation SA
@@ -63137,6 +64208,9 @@ OUI:70B3D5D62*
OUI:70B3D5D63*
ID_OUI_FROM_DATABASE=CRDE
+OUI:70B3D5D64*
+ ID_OUI_FROM_DATABASE=Mettler Toledo Hi Speed
+
OUI:70B3D5D65*
ID_OUI_FROM_DATABASE=CRDE
@@ -63167,6 +64241,9 @@ OUI:70B3D5D6F*
OUI:70B3D5D70*
ID_OUI_FROM_DATABASE=Rational Production srl Unipersonale
+OUI:70B3D5D71*
+ ID_OUI_FROM_DATABASE=RZB Rudolf Zimmermann, Bamberg GmbH
+
OUI:70B3D5D72*
ID_OUI_FROM_DATABASE=OnYield Inc Ltd
@@ -63278,6 +64355,12 @@ OUI:70B3D5DA1*
OUI:70B3D5DA4*
ID_OUI_FROM_DATABASE=CRDE
+OUI:70B3D5DA5*
+ ID_OUI_FROM_DATABASE=Roboteq
+
+OUI:70B3D5DA6*
+ ID_OUI_FROM_DATABASE=Redfish Group Pty Ltd
+
OUI:70B3D5DA8*
ID_OUI_FROM_DATABASE=Tagarno AS
@@ -63302,6 +64385,9 @@ OUI:70B3D5DB4*
OUI:70B3D5DB5*
ID_OUI_FROM_DATABASE=Xiamen Point Circle Technologh Co,ltd
+OUI:70B3D5DB6*
+ ID_OUI_FROM_DATABASE=csintech
+
OUI:70B3D5DB8*
ID_OUI_FROM_DATABASE=SISTEM SA
@@ -63377,6 +64463,9 @@ OUI:70B3D5DE8*
OUI:70B3D5DE9*
ID_OUI_FROM_DATABASE=Private
+OUI:70B3D5DEA*
+ ID_OUI_FROM_DATABASE=Advanced Ventilation Applications, Inc.
+
OUI:70B3D5DEC*
ID_OUI_FROM_DATABASE=Condev-Automation GmbH
@@ -63482,6 +64571,9 @@ OUI:70B3D5E27*
OUI:70B3D5E28*
ID_OUI_FROM_DATABASE=iotec GmbH
+OUI:70B3D5E2B*
+ ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd.
+
OUI:70B3D5E2C*
ID_OUI_FROM_DATABASE=Fourth Frontier Technologies Private Limited
@@ -63515,6 +64607,9 @@ OUI:70B3D5E3E*
OUI:70B3D5E3F*
ID_OUI_FROM_DATABASE=BESTCODE LLC
+OUI:70B3D5E43*
+ ID_OUI_FROM_DATABASE=SL Audio A/S
+
OUI:70B3D5E45*
ID_OUI_FROM_DATABASE=Momentum Data Systems
@@ -63542,6 +64637,9 @@ OUI:70B3D5E4F*
OUI:70B3D5E50*
ID_OUI_FROM_DATABASE=Advanced Vision Technology Ltd
+OUI:70B3D5E52*
+ ID_OUI_FROM_DATABASE=Guangzhou Moblin Technology Co., Ltd.
+
OUI:70B3D5E53*
ID_OUI_FROM_DATABASE=MI INC.
@@ -63560,6 +64658,9 @@ OUI:70B3D5E59*
OUI:70B3D5E5E*
ID_OUI_FROM_DATABASE=Critical Link LLC
+OUI:70B3D5E61*
+ ID_OUI_FROM_DATABASE=Adeli
+
OUI:70B3D5E67*
ID_OUI_FROM_DATABASE=APPLIED PROCESSING
@@ -63680,6 +64781,9 @@ OUI:70B3D5EA6*
OUI:70B3D5EA7*
ID_OUI_FROM_DATABASE=S.I.C.E.S. srl
+OUI:70B3D5EA8*
+ ID_OUI_FROM_DATABASE=Dia-Stron Limited
+
OUI:70B3D5EAB*
ID_OUI_FROM_DATABASE=APEN GROUP SpA (VAT IT08767740155)
@@ -63701,6 +64805,9 @@ OUI:70B3D5EB2*
OUI:70B3D5EB3*
ID_OUI_FROM_DATABASE=KWS-Electronic GmbH
+OUI:70B3D5EB4*
+ ID_OUI_FROM_DATABASE=Robotic Research, LLC
+
OUI:70B3D5EB5*
ID_OUI_FROM_DATABASE=JUSTEK INC
@@ -63749,6 +64856,9 @@ OUI:70B3D5ECE*
OUI:70B3D5ECF*
ID_OUI_FROM_DATABASE=Ipitek
+OUI:70B3D5ED0*
+ ID_OUI_FROM_DATABASE=shanghai qiaoqi zhinengkeji
+
OUI:70B3D5ED1*
ID_OUI_FROM_DATABASE=Przemyslowy Instytut Automatyki i Pomiarow
@@ -63782,12 +64892,18 @@ OUI:70B3D5EE5*
OUI:70B3D5EEA*
ID_OUI_FROM_DATABASE=Dameca a/s
+OUI:70B3D5EEC*
+ ID_OUI_FROM_DATABASE=Impolux GmbH
+
OUI:70B3D5EED*
ID_OUI_FROM_DATABASE=COMM-connect A/S
OUI:70B3D5EEE*
ID_OUI_FROM_DATABASE=SOCIEDAD IBERICA DE CONSTRUCCIONES ELECTRICAS, S.A. (SICE)
+OUI:70B3D5EEF*
+ ID_OUI_FROM_DATABASE=TATTILE SRL
+
OUI:70B3D5EF2*
ID_OUI_FROM_DATABASE=Kongsberg Intergrated Tactical Systems
@@ -63863,6 +64979,9 @@ OUI:70B3D5F12*
OUI:70B3D5F13*
ID_OUI_FROM_DATABASE=MEDIAM Sp. z o.o.
+OUI:70B3D5F14*
+ ID_OUI_FROM_DATABASE=SANYU SWITCH CO., LTD.
+
OUI:70B3D5F17*
ID_OUI_FROM_DATABASE=VITEC
@@ -63939,11 +65058,14 @@ OUI:70B3D5F4C*
ID_OUI_FROM_DATABASE=Global Lightning Protection Services A(S
OUI:70B3D5F4D*
- ID_OUI_FROM_DATABASE=Honeywell International Inc.
+ ID_OUI_FROM_DATABASE=Honeywell
OUI:70B3D5F4F*
ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L.
+OUI:70B3D5F52*
+ ID_OUI_FROM_DATABASE=Alere Technologies AS
+
OUI:70B3D5F54*
ID_OUI_FROM_DATABASE=Revolution Retail Systems
@@ -63956,6 +65078,9 @@ OUI:70B3D5F56*
OUI:70B3D5F57*
ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+OUI:70B3D5F58*
+ ID_OUI_FROM_DATABASE=CDR SRL
+
OUI:70B3D5F5A*
ID_OUI_FROM_DATABASE=HAMEG GmbH
@@ -64031,12 +65156,18 @@ OUI:70B3D5F81*
OUI:70B3D5F83*
ID_OUI_FROM_DATABASE=Tata Communications Ltd.
+OUI:70B3D5F84*
+ ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
+
OUI:70B3D5F85*
ID_OUI_FROM_DATABASE=Solystic
OUI:70B3D5F87*
ID_OUI_FROM_DATABASE=SHINWA INDUSTRIES, INC.
+OUI:70B3D5F8A*
+ ID_OUI_FROM_DATABASE=FRS GmbH & Co. KG
+
OUI:70B3D5F8B*
ID_OUI_FROM_DATABASE=IOOOTA Srl
@@ -64157,6 +65288,9 @@ OUI:70B3D5FC5*
OUI:70B3D5FC6*
ID_OUI_FROM_DATABASE=Tecnint HTE SRL
+OUI:70B3D5FC8*
+ ID_OUI_FROM_DATABASE=Moduware PTY LTD
+
OUI:70B3D5FC9*
ID_OUI_FROM_DATABASE=Shanghai EICT Global Service Co., Ltd
@@ -64220,6 +65354,9 @@ OUI:70B3D5FE8*
OUI:70B3D5FE9*
ID_OUI_FROM_DATABASE=Camsat Przemysław Gralak
+OUI:70B3D5FEA*
+ ID_OUI_FROM_DATABASE=Heng Dian Technology Co., Ltd
+
OUI:70B3D5FEB*
ID_OUI_FROM_DATABASE=Les distributions Multi-Secure incorporee
@@ -64265,6 +65402,9 @@ OUI:70B3D5FFF*
OUI:70B599*
ID_OUI_FROM_DATABASE=Embedded Technologies s.r.o.
+OUI:70B7AA*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:70B7E2*
ID_OUI_FROM_DATABASE=Jiangsu Miter Technology Co.,Ltd.
@@ -64463,6 +65603,9 @@ OUI:70F96D*
OUI:70FC8C*
ID_OUI_FROM_DATABASE=OneAccess SA
+OUI:70FD46*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:70FF5C*
ID_OUI_FROM_DATABASE=Cheerzing Communication(Xiamen)Technology Co.,Ltd
@@ -64475,6 +65618,9 @@ OUI:7403BD*
OUI:74042B*
ID_OUI_FROM_DATABASE=Lenovo Mobile Communication (Wuhan) Company Limited
+OUI:7405A5*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:740ABC*
ID_OUI_FROM_DATABASE=LightwaveRF Technology Ltd
@@ -64598,6 +65744,9 @@ OUI:741E93*
OUI:741F4A*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+OUI:741F79*
+ ID_OUI_FROM_DATABASE=YOUNGKOOK ELECTRONICS CO.,LTD
+
OUI:742344*
ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
@@ -64640,6 +65789,9 @@ OUI:743170*
OUI:743256*
ID_OUI_FROM_DATABASE=NT-ware Systemprg GmbH
+OUI:743400*
+ ID_OUI_FROM_DATABASE=MTG Co., Ltd.
+
OUI:74372F*
ID_OUI_FROM_DATABASE=Tongfang Shenzhen Cloudcomputing Technology Co.,Ltd
@@ -64697,6 +65849,9 @@ OUI:745612*
OUI:745798*
ID_OUI_FROM_DATABASE=TRUMPF Laser GmbH + Co. KG
+OUI:745933*
+ ID_OUI_FROM_DATABASE=Danal Entertainment
+
OUI:745AAA*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -64799,6 +65954,9 @@ OUI:748114*
OUI:74819A*
ID_OUI_FROM_DATABASE=PT. Hartono Istana Teknologi
+OUI:7483C2*
+ ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
+
OUI:7483EF*
ID_OUI_FROM_DATABASE=Arista Networks
@@ -64814,6 +65972,9 @@ OUI:74867A*
OUI:7487A9*
ID_OUI_FROM_DATABASE=OCT Technology Co., Ltd.
+OUI:7487BB*
+ ID_OUI_FROM_DATABASE=Ciena Corporation
+
OUI:74882A*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -65246,6 +66407,9 @@ OUI:780473*
OUI:780541*
ID_OUI_FROM_DATABASE=Queclink Wireless Solutions Co., Ltd
+OUI:78055F*
+ ID_OUI_FROM_DATABASE=Shenzhen WYC Technology Co., Ltd.
+
OUI:780738*
ID_OUI_FROM_DATABASE=Z.U.K. Elzab S.A.
@@ -65255,6 +66419,9 @@ OUI:780AC7*
OUI:780CB8*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:780CF0*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:780F77*
ID_OUI_FROM_DATABASE=HangZhou Gubei Electronics Technology Co.,Ltd
@@ -65327,6 +66494,9 @@ OUI:782D7E*
OUI:782EEF*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:782F17*
+ ID_OUI_FROM_DATABASE=Xlab Co.,Ltd
+
OUI:78303B*
ID_OUI_FROM_DATABASE=Stephen Technologies Co.,Limited
@@ -65414,6 +66584,9 @@ OUI:78510C*
OUI:78521A*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:78524A*
+ ID_OUI_FROM_DATABASE=Ensenso GmbH
+
OUI:785262*
ID_OUI_FROM_DATABASE=Shenzhen Hojy Software Co., Ltd.
@@ -65906,6 +67079,9 @@ OUI:78D800E*
OUI:78D99F*
ID_OUI_FROM_DATABASE=NuCom HK Ltd.
+OUI:78DA07*
+ ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd.
+
OUI:78DA6E*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -66020,6 +67196,9 @@ OUI:7C02BC*
OUI:7C034C*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:7C03AB*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:7C03C9*
ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
@@ -66104,6 +67283,9 @@ OUI:7C2048*
OUI:7C2064*
ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD
+OUI:7C240C*
+ ID_OUI_FROM_DATABASE=Telechips, Inc.
+
OUI:7C2586*
ID_OUI_FROM_DATABASE=Juniper Networks
@@ -66284,6 +67466,9 @@ OUI:7C669D*
OUI:7C67A2*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:7C696B*
+ ID_OUI_FROM_DATABASE=Atmosic Technologies
+
OUI:7C69F6*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -66305,6 +67490,9 @@ OUI:7C6B33*
OUI:7C6B52*
ID_OUI_FROM_DATABASE=Tigaro Wireless
+OUI:7C6B9C*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:7C6BF7*
ID_OUI_FROM_DATABASE=NTI co., ltd.
@@ -66317,6 +67505,9 @@ OUI:7C6C8F*
OUI:7C6D62*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:7C6DA6*
+ ID_OUI_FROM_DATABASE=Superwave Group LLC
+
OUI:7C6DF8*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -66455,6 +67646,9 @@ OUI:7C96D2*
OUI:7C9763*
ID_OUI_FROM_DATABASE=Openmatics s.r.o.
+OUI:7C9A54*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
OUI:7C9A9B*
ID_OUI_FROM_DATABASE=VSE valencia smart energy
@@ -66675,7 +67869,7 @@ OUI:7CD1C3*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:7CD30A*
- ID_OUI_FROM_DATABASE=INVENTEC Corporation
+ ID_OUI_FROM_DATABASE=INVENTEC CORPORATION
OUI:7CD762*
ID_OUI_FROM_DATABASE=Freestyle Technology Pty Ltd
@@ -66926,6 +68120,9 @@ OUI:802FDE*
OUI:8030DC*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:8030E0*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
OUI:803457*
ID_OUI_FROM_DATABASE=OT Systems Limited
@@ -66953,6 +68150,9 @@ OUI:803A0A*
OUI:803A59*
ID_OUI_FROM_DATABASE=AT&T
+OUI:803AF4*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:803B2A*
ID_OUI_FROM_DATABASE=ABB Xiamen Low Voltage Equipment Co.,Ltd.
@@ -67028,6 +68228,9 @@ OUI:805A04*
OUI:805E0C*
ID_OUI_FROM_DATABASE=YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD.
+OUI:805E4F*
+ ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED
+
OUI:805EC0*
ID_OUI_FROM_DATABASE=YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD.
@@ -67064,6 +68267,9 @@ OUI:806C8B*
OUI:806CBC*
ID_OUI_FROM_DATABASE=NET New Electronic Technology GmbH
+OUI:806FB0*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:80711F*
ID_OUI_FROM_DATABASE=Juniper Networks
@@ -67184,6 +68390,9 @@ OUI:809393*
OUI:80946C*
ID_OUI_FROM_DATABASE=TOKYO RADAR CORPORATION
+OUI:809621*
+ ID_OUI_FROM_DATABASE=Lenovo
+
OUI:8096B1*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -67211,6 +68420,9 @@ OUI:80A1D7*
OUI:80A589*
ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+OUI:80A796*
+ ID_OUI_FROM_DATABASE=Neurotek LLC
+
OUI:80A85D*
ID_OUI_FROM_DATABASE=Osterhout Design Group
@@ -67244,6 +68456,9 @@ OUI:80B32A*
OUI:80B575*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:80B624*
+ ID_OUI_FROM_DATABASE=IVS
+
OUI:80B686*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -67304,6 +68519,9 @@ OUI:80CE62*
OUI:80CEB1*
ID_OUI_FROM_DATABASE=Theissen Training Systems GmbH
+OUI:80CEB9*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:80CF41*
ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd.
@@ -67440,7 +68658,7 @@ OUI:84002D*
ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
OUI:8400D2*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:8401A7*
ID_OUI_FROM_DATABASE=Greyware Automation Products, Inc
@@ -67472,6 +68690,9 @@ OUI:841715*
OUI:841766*
ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD
+OUI:8417EF*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
OUI:841826*
ID_OUI_FROM_DATABASE=Osram GmbH
@@ -67691,6 +68912,9 @@ OUI:84683E*
OUI:846878*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:846A66*
+ ID_OUI_FROM_DATABASE=Sumitomo Kizai Co.,Ltd.
+
OUI:846AED*
ID_OUI_FROM_DATABASE=Wireless Tsukamoto.,co.LTD
@@ -67769,6 +68993,54 @@ OUI:8486F3*
OUI:8489AD*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:8489EC0*
+ ID_OUI_FROM_DATABASE=SmartGiant Technology
+
+OUI:8489EC1*
+ ID_OUI_FROM_DATABASE=Research Electronics International, LLC.
+
+OUI:8489EC2*
+ ID_OUI_FROM_DATABASE=thousand star tech LTD.
+
+OUI:8489EC3*
+ ID_OUI_FROM_DATABASE=Aerionics Inc.
+
+OUI:8489EC4*
+ ID_OUI_FROM_DATABASE=Vayyar Imaging Ltd.
+
+OUI:8489EC5*
+ ID_OUI_FROM_DATABASE=Zephyr Engineering, Inc.
+
+OUI:8489EC6*
+ ID_OUI_FROM_DATABASE=POCT biotechnology
+
+OUI:8489EC7*
+ ID_OUI_FROM_DATABASE=BYDA Co. Ltd.,
+
+OUI:8489EC8*
+ ID_OUI_FROM_DATABASE=Arts Digital Technology (HK) Ltd.
+
+OUI:8489EC9*
+ ID_OUI_FROM_DATABASE=Shenzhen Xtooltech Co., Ltd
+
+OUI:8489ECA*
+ ID_OUI_FROM_DATABASE=Newell Brands
+
+OUI:8489ECB*
+ ID_OUI_FROM_DATABASE=EPSa Elektronik & Präzisionsbau Saalfeld GmbH
+
+OUI:8489ECC*
+ ID_OUI_FROM_DATABASE=SHINKAWA LTD.
+
+OUI:8489ECD*
+ ID_OUI_FROM_DATABASE=Price Industries Limited
+
+OUI:8489ECE*
+ ID_OUI_FROM_DATABASE=Shenzhen Intellifusion Technologies Co., Ltd.
+
+OUI:848A8D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:848D84*
ID_OUI_FROM_DATABASE=Rajant Corporation
@@ -67782,7 +69054,7 @@ OUI:848E96*
ID_OUI_FROM_DATABASE=Embertec Pty Ltd
OUI:848EDF*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:848F69*
ID_OUI_FROM_DATABASE=Dell Inc.
@@ -67826,6 +69098,9 @@ OUI:84A134*
OUI:84A1D1*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:84A24D*
+ ID_OUI_FROM_DATABASE=Birds Eye Systems Private Limited
+
OUI:84A423*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
@@ -67874,6 +69149,9 @@ OUI:84B153*
OUI:84B261*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:84B31B*
+ ID_OUI_FROM_DATABASE=Kinexon GmbH
+
OUI:84B517*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -67911,7 +69189,7 @@ OUI:84C7A9*
ID_OUI_FROM_DATABASE=C3PO S.A.
OUI:84C7EA*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:84C8B1*
ID_OUI_FROM_DATABASE=Incognito Software Systems Inc.
@@ -67919,6 +69197,9 @@ OUI:84C8B1*
OUI:84C9B2*
ID_OUI_FROM_DATABASE=D-Link International
+OUI:84C9C6*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
OUI:84CD62*
ID_OUI_FROM_DATABASE=ShenZhen IDWELL Technology CO.,Ltd
@@ -68072,6 +69353,9 @@ OUI:84FE9E*
OUI:84FEDC*
ID_OUI_FROM_DATABASE=Borqs Beijing Ltd.
+OUI:880118*
+ ID_OUI_FROM_DATABASE=BLT Co
+
OUI:8801F2*
ID_OUI_FROM_DATABASE=Vitec System Engineering Inc.
@@ -68084,6 +69368,9 @@ OUI:88074B*
OUI:880905*
ID_OUI_FROM_DATABASE=MTMCommunications
+OUI:880907*
+ ID_OUI_FROM_DATABASE=MKT Systemtechnik GmbH & Co. KG
+
OUI:8809AF*
ID_OUI_FROM_DATABASE=Masimo Corporation
@@ -68096,6 +69383,9 @@ OUI:880FB6*
OUI:881036*
ID_OUI_FROM_DATABASE=Panodic(ShenZhen) Electronics Limted
+OUI:88108F*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:881196*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -68171,9 +69461,15 @@ OUI:883314*
OUI:8833BE*
ID_OUI_FROM_DATABASE=Ivenix, Inc.
+OUI:8834FE*
+ ID_OUI_FROM_DATABASE=Bosch Automotive Products (Suzhou) Co. Ltd
+
OUI:88354C*
ID_OUI_FROM_DATABASE=Transics
+OUI:8835C1*
+ ID_OUI_FROM_DATABASE=OI ELECTRIC CO.,LTD
+
OUI:883612*
ID_OUI_FROM_DATABASE=SRC Computers, LLC
@@ -68195,6 +69491,9 @@ OUI:883D24*
OUI:883F4A*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:883F99*
+ ID_OUI_FROM_DATABASE=Siemens AG
+
OUI:883FD3*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -68498,6 +69797,9 @@ OUI:8896B6*
OUI:8896F2*
ID_OUI_FROM_DATABASE=Valeo Schalter und Sensoren GmbH
+OUI:889765*
+ ID_OUI_FROM_DATABASE=exands
+
OUI:8897DF*
ID_OUI_FROM_DATABASE=Entrypass Corporation Sdn. Bhd.
@@ -68510,6 +69812,9 @@ OUI:889B39*
OUI:889CA6*
ID_OUI_FROM_DATABASE=BTB Korea INC
+OUI:889F6F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:889FFA*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -68612,6 +69917,9 @@ OUI:88B4A6*
OUI:88B627*
ID_OUI_FROM_DATABASE=Gembird Europe BV
+OUI:88B66B*
+ ID_OUI_FROM_DATABASE=easynetworks
+
OUI:88B6EE*
ID_OUI_FROM_DATABASE=Dish Technologies Corp
@@ -68630,6 +69938,9 @@ OUI:88BD78*
OUI:88BFD5*
ID_OUI_FROM_DATABASE=Simple Audio Ltd
+OUI:88BFE4*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:88C242*
ID_OUI_FROM_DATABASE=Poynt Co.
@@ -68675,6 +69986,9 @@ OUI:88D171*
OUI:88D274*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:88D2BF*
+ ID_OUI_FROM_DATABASE=German Autolabs
+
OUI:88D37B*
ID_OUI_FROM_DATABASE=FirmTek, LLC
@@ -68708,6 +70022,9 @@ OUI:88DE7C*
OUI:88DEA9*
ID_OUI_FROM_DATABASE=Roku, Inc.
+OUI:88DF9E*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
OUI:88E0A0*
ID_OUI_FROM_DATABASE=Shenzhen VisionSTOR Technologies Co., Ltd
@@ -68762,6 +70079,9 @@ OUI:88F488*
OUI:88F490*
ID_OUI_FROM_DATABASE=Jetmobile Pte Ltd
+OUI:88F7BF*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:88F7C7*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
@@ -68858,6 +70178,9 @@ OUI:8C147DD*
OUI:8C147DE*
ID_OUI_FROM_DATABASE=Electrical & Automation Larsen & Toubro Limited
+OUI:8C14B4*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:8C15C7*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -68954,6 +70277,9 @@ OUI:8C1CDAB*
OUI:8C1CDAC*
ID_OUI_FROM_DATABASE=Alcidae Inc
+OUI:8C1CDAD*
+ ID_OUI_FROM_DATABASE=Riegl Laser Measurement Systems GmbH
+
OUI:8C1CDAE*
ID_OUI_FROM_DATABASE=Electronic Controlled Systems, Inc.
@@ -68993,6 +70319,9 @@ OUI:8C3357*
OUI:8C34FD*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:8C3579*
+ ID_OUI_FROM_DATABASE=QDIQO Sp. z o.o.
+
OUI:8C395C*
ID_OUI_FROM_DATABASE=Bit4id Srl
@@ -69011,6 +70340,9 @@ OUI:8C3C4A*
OUI:8C41F2*
ID_OUI_FROM_DATABASE=RDA Technologies Ltd.
+OUI:8C41F4*
+ ID_OUI_FROM_DATABASE=IPmotion GmbH
+
OUI:8C4435*
ID_OUI_FROM_DATABASE=Shanghai BroadMobi Communication Technology Co., Ltd.
@@ -69095,11 +70427,14 @@ OUI:8C60E7*
OUI:8C6102*
ID_OUI_FROM_DATABASE=Beijing Baofengmojing Technologies Co., Ltd
+OUI:8C61A3*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:8C640B*
ID_OUI_FROM_DATABASE=Beyond Devices d.o.o.
OUI:8C6422*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:8C6878*
ID_OUI_FROM_DATABASE=Nortek-AS
@@ -69110,6 +70445,9 @@ OUI:8C6AE4*
OUI:8C6D50*
ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD
+OUI:8C6D77*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:8C705A*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -69152,12 +70490,18 @@ OUI:8C7EB3*
OUI:8C7F3B*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:8C8126*
+ ID_OUI_FROM_DATABASE=ARCOM
+
OUI:8C82A8*
ID_OUI_FROM_DATABASE=Insigma Technology Co.,Ltd
OUI:8C839D*
ID_OUI_FROM_DATABASE=SHENZHEN XINYUPENG ELECTRONIC TECHNOLOGY CO., LTD
+OUI:8C83E1*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:8C8401*
ID_OUI_FROM_DATABASE=Private
@@ -69191,6 +70535,9 @@ OUI:8C8E76*
OUI:8C8EF2*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:8C8F8B*
+ ID_OUI_FROM_DATABASE=China Mobile Chongqing branch
+
OUI:8C8FE9*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -69203,6 +70550,9 @@ OUI:8C9109*
OUI:8C9236*
ID_OUI_FROM_DATABASE=Aus.Linx Technology Co., Ltd.
+OUI:8C9246*
+ ID_OUI_FROM_DATABASE=Oerlikon Textile Gmbh&Co.KG
+
OUI:8C9351*
ID_OUI_FROM_DATABASE=Jigowatts Inc.
@@ -69242,6 +70592,9 @@ OUI:8CAE89*
OUI:8CB094*
ID_OUI_FROM_DATABASE=Airtech I&C Co., Ltd
+OUI:8CB0E9*
+ ID_OUI_FROM_DATABASE=Samsung Electronics.,LTD
+
OUI:8CB64F*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -69434,6 +70787,9 @@ OUI:8CFABA*
OUI:8CFDF0*
ID_OUI_FROM_DATABASE=Qualcomm Inc.
+OUI:8CFE74*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
OUI:8CFEB4*
ID_OUI_FROM_DATABASE=VSOONTECH ELECTRONICS CO., LIMITED
@@ -69548,6 +70904,9 @@ OUI:9027E4*
OUI:902B34*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+OUI:902BD2*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:902CC7*
ID_OUI_FROM_DATABASE=C-MAX Asia Limited
@@ -69626,6 +70985,9 @@ OUI:90489A*
OUI:9049FA*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:904C81*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
OUI:904CE5*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -69936,7 +71298,7 @@ OUI:90B97D*
ID_OUI_FROM_DATABASE=Johnson Outdoors Marine Electronics d/b/a Minnkota
OUI:90C115*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:90C1C6*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -70190,6 +71552,9 @@ OUI:94282E*
OUI:94290C*
ID_OUI_FROM_DATABASE=Shenyang wisdom Foundation Technology Development Co., Ltd.
+OUI:94298D*
+ ID_OUI_FROM_DATABASE=Shanghai AdaptComm Technology Co., Ltd.
+
OUI:942A3F*
ID_OUI_FROM_DATABASE=Diversey Inc
@@ -70385,6 +71750,9 @@ OUI:948E89*
OUI:948FEE*
ID_OUI_FROM_DATABASE=Verizon Telematics
+OUI:94917F*
+ ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
+
OUI:9492BC*
ID_OUI_FROM_DATABASE=SYNTECH(HK) TECHNOLOGY LIMITED
@@ -70406,6 +71774,9 @@ OUI:949990*
OUI:949AA9*
ID_OUI_FROM_DATABASE=Microsoft Corporation
+OUI:949B2C*
+ ID_OUI_FROM_DATABASE=Extreme Networks, Inc.
+
OUI:949BFD*
ID_OUI_FROM_DATABASE=Trans New Technology, Inc.
@@ -70430,6 +71801,9 @@ OUI:94A04E*
OUI:94A1A2*
ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
+OUI:94A3CA*
+ ID_OUI_FROM_DATABASE=KonnectONE, LLC
+
OUI:94A7B7*
ID_OUI_FROM_DATABASE=zte corporation
@@ -70500,7 +71874,7 @@ OUI:94C150*
ID_OUI_FROM_DATABASE=2Wire Inc
OUI:94C3E4*
- ID_OUI_FROM_DATABASE=SCA Schucker Gmbh & Co KG
+ ID_OUI_FROM_DATABASE=Atlas Copco IAS GmbH
OUI:94C4E9*
ID_OUI_FROM_DATABASE=PowerLayer Microsystems HongKong Limited
@@ -70530,7 +71904,7 @@ OUI:94CDAC*
ID_OUI_FROM_DATABASE=Creowave Oy
OUI:94CE2C*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:94CE31*
ID_OUI_FROM_DATABASE=CTS Limited
@@ -70739,6 +72113,9 @@ OUI:9802D8E*
OUI:9802D8F*
ID_OUI_FROM_DATABASE=Private
+OUI:98039B*
+ ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc.
+
OUI:9803A0*
ID_OUI_FROM_DATABASE=ABB n.v. Power Quality Products
@@ -71042,6 +72419,9 @@ OUI:988E34*
OUI:988E4A*
ID_OUI_FROM_DATABASE=NOXUS(BEIJING) TECHNOLOGY CO.,LTD
+OUI:988ED4*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
OUI:988EDD*
ID_OUI_FROM_DATABASE=TE Connectivity Limerick
@@ -71126,6 +72506,9 @@ OUI:98AAFCD*
OUI:98AAFCE*
ID_OUI_FROM_DATABASE=Comarch S.A.
+OUI:98AE71*
+ ID_OUI_FROM_DATABASE=VVDN Technologies Pvt Ltd
+
OUI:98B039*
ID_OUI_FROM_DATABASE=Nokia
@@ -71138,6 +72521,9 @@ OUI:98B8E3*
OUI:98BB1E*
ID_OUI_FROM_DATABASE=BYD Precision Manufacture Company Ltd.
+OUI:98BB99*
+ ID_OUI_FROM_DATABASE=Phicomm (Sichuan) Co.,Ltd.
+
OUI:98BC57*
ID_OUI_FROM_DATABASE=SVA TECHNOLOGIES CO.LTD
@@ -71315,6 +72701,9 @@ OUI:9C061B*
OUI:9C066E*
ID_OUI_FROM_DATABASE=Hytera Communications Corporation Limited
+OUI:9C0CDF*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:9C0DAC*
ID_OUI_FROM_DATABASE=Tymphany HK Limited
@@ -71519,6 +72908,9 @@ OUI:9C5711*
OUI:9C57AD*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:9C5A44*
+ ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
+
OUI:9C5B96*
ID_OUI_FROM_DATABASE=NMR Corporation
@@ -71529,7 +72921,7 @@ OUI:9C5C8E*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
OUI:9C5CF9*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:9C5D12*
ID_OUI_FROM_DATABASE=Aerohive Networks Inc.
@@ -71604,7 +72996,7 @@ OUI:9C7DA3*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:9C7F57*
- ID_OUI_FROM_DATABASE=DERA Co. Ltd
+ ID_OUI_FROM_DATABASE=UNIC Memory Technology Co Ltd
OUI:9C807D*
ID_OUI_FROM_DATABASE=SYSCABLE Korea Inc.
@@ -71708,6 +73100,9 @@ OUI:9CA69D*
OUI:9CA9E4*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:9CAA1B*
+ ID_OUI_FROM_DATABASE=Microsoft Corporation
+
OUI:9CAC6D*
ID_OUI_FROM_DATABASE=Universal Electronics, Inc.
@@ -71774,6 +73169,9 @@ OUI:9CC7D1*
OUI:9CC8AE*
ID_OUI_FROM_DATABASE=Becton, Dickinson and Company
+OUI:9CC950*
+ ID_OUI_FROM_DATABASE=Baumer Holding
+
OUI:9CCAD9*
ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -71882,6 +73280,51 @@ OUI:9CF61A*
OUI:9CF67D*
ID_OUI_FROM_DATABASE=Ricardo Prague, s.r.o.
+OUI:9CF6DD0*
+ ID_OUI_FROM_DATABASE=annapurnalabs
+
+OUI:9CF6DD1*
+ ID_OUI_FROM_DATABASE=Ithor IT Co.,Ltd.
+
+OUI:9CF6DD2*
+ ID_OUI_FROM_DATABASE=Beijing Sifang Automation Co., Ltd.
+
+OUI:9CF6DD3*
+ ID_OUI_FROM_DATABASE=RYEEX Technology Co.,Ltd.
+
+OUI:9CF6DD4*
+ ID_OUI_FROM_DATABASE=Capital Engineering & Research Incorporation Ltd.
+
+OUI:9CF6DD5*
+ ID_OUI_FROM_DATABASE=b8ta Inc.
+
+OUI:9CF6DD6*
+ ID_OUI_FROM_DATABASE=Shenzhen Xtooltech Co., Ltd
+
+OUI:9CF6DD7*
+ ID_OUI_FROM_DATABASE=KXT Technology Co., Ltd.
+
+OUI:9CF6DD8*
+ ID_OUI_FROM_DATABASE=Savari Inc
+
+OUI:9CF6DD9*
+ ID_OUI_FROM_DATABASE=CAMA(Luoyang)Electronics Co.,Ltd
+
+OUI:9CF6DDA*
+ ID_OUI_FROM_DATABASE=AVI Pty Ltd
+
+OUI:9CF6DDB*
+ ID_OUI_FROM_DATABASE=Guangzhou LANGO Electronics Technology Co., Ltd.
+
+OUI:9CF6DDC*
+ ID_OUI_FROM_DATABASE=Lighting New Energy Technology Co., Ltd.
+
+OUI:9CF6DDD*
+ ID_OUI_FROM_DATABASE=Foshan Synwit Technology Co.,Ltd.
+
+OUI:9CF6DDE*
+ ID_OUI_FROM_DATABASE=Shanxi ZhuoZhi fei High Electronic Technology Co. Ltd.
+
OUI:9CF8DB*
ID_OUI_FROM_DATABASE=shenzhen eyunmei technology co,.ltd
@@ -71975,15 +73418,51 @@ OUI:A01859*
OUI:A01917*
ID_OUI_FROM_DATABASE=Bertel S.p.a.
+OUI:A019B20*
+ ID_OUI_FROM_DATABASE=Vast Production Services
+
OUI:A019B21*
ID_OUI_FROM_DATABASE=El Sewedy Electrometer Egypt S.A.E.
OUI:A019B22*
ID_OUI_FROM_DATABASE=Beijing Deephi Intelligent Technology Co., Ltd
+OUI:A019B23*
+ ID_OUI_FROM_DATABASE=Power Diagnostic Service Co., LTD.
+
+OUI:A019B24*
+ ID_OUI_FROM_DATABASE=Osatec
+
+OUI:A019B25*
+ ID_OUI_FROM_DATABASE=SZBROAD TECHNOLOGY (HK) CO.,LTMITED
+
+OUI:A019B26*
+ ID_OUI_FROM_DATABASE=GfG mbH
+
+OUI:A019B27*
+ ID_OUI_FROM_DATABASE=ARIMA Communications Corp.
+
OUI:A019B28*
ID_OUI_FROM_DATABASE=MIS Industrie Systeme GmbH & Co. KG
+OUI:A019B29*
+ ID_OUI_FROM_DATABASE=Lon Microsystems Inc.
+
+OUI:A019B2A*
+ ID_OUI_FROM_DATABASE=Adomi
+
+OUI:A019B2B*
+ ID_OUI_FROM_DATABASE=HangZhou iMagic Technology Co., Ltd
+
+OUI:A019B2C*
+ ID_OUI_FROM_DATABASE=LDA Technologies
+
+OUI:A019B2D*
+ ID_OUI_FROM_DATABASE=RYD Electronic Technology Co.,Ltd.
+
+OUI:A019B2E*
+ ID_OUI_FROM_DATABASE=Ahgora Sistemas SA
+
OUI:A01B29*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
@@ -72011,6 +73490,51 @@ OUI:A0231B*
OUI:A0239F*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:A028330*
+ ID_OUI_FROM_DATABASE=GERSYS GmbH
+
+OUI:A028331*
+ ID_OUI_FROM_DATABASE=Ordercube GmbH
+
+OUI:A028332*
+ ID_OUI_FROM_DATABASE=Shanghai Nohmi Secom Fire Protection Equipment Co.,Ltd.
+
+OUI:A028333*
+ ID_OUI_FROM_DATABASE=SHANGHAI XUNTAI INFORMATION TECHNOLOGY CO.,LTD.
+
+OUI:A028334*
+ ID_OUI_FROM_DATABASE=Firm INFORMTEST Ltd.
+
+OUI:A028335*
+ ID_OUI_FROM_DATABASE=JGR Optics Inc
+
+OUI:A028336*
+ ID_OUI_FROM_DATABASE=Xiamen Caimore Communication Technology Co.,Ltd.
+
+OUI:A028337*
+ ID_OUI_FROM_DATABASE=Kryptus Information Security S/A
+
+OUI:A028338*
+ ID_OUI_FROM_DATABASE=HZHY TECHNOLOGY
+
+OUI:A028339*
+ ID_OUI_FROM_DATABASE=IMESHX CORPORATION LIMITED
+
+OUI:A02833A*
+ ID_OUI_FROM_DATABASE=Medical Evolution Kft
+
+OUI:A02833B*
+ ID_OUI_FROM_DATABASE=FlexLink AB
+
+OUI:A02833C*
+ ID_OUI_FROM_DATABASE=Kalray S.A.
+
+OUI:A02833D*
+ ID_OUI_FROM_DATABASE=Audix
+
+OUI:A02833E*
+ ID_OUI_FROM_DATABASE=Precision Planting, LLC.
+
OUI:A02BB8*
ID_OUI_FROM_DATABASE=Hewlett Packard
@@ -72314,8 +73838,11 @@ OUI:A091C8*
OUI:A09347*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+OUI:A09351*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:A0950C*
- ID_OUI_FROM_DATABASE=China Mobile IOTCompany Limited
+ ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited
OUI:A09805*
ID_OUI_FROM_DATABASE=OpenVox Communication Co Ltd
@@ -72480,7 +74007,7 @@ OUI:A0C589*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:A0C5F20*
- ID_OUI_FROM_DATABASE=Private
+ ID_OUI_FROM_DATABASE=Quantlab Financial, LLC
OUI:A0C5F21*
ID_OUI_FROM_DATABASE=KNS Group LLC (YADRO Company)
@@ -72554,6 +74081,9 @@ OUI:A0D385*
OUI:A0D3C1*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:A0D635*
+ ID_OUI_FROM_DATABASE=WBS Technology
+
OUI:A0D795*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -72588,7 +74118,7 @@ OUI:A0E295*
ID_OUI_FROM_DATABASE=DAT System Co.,Ltd
OUI:A0E453*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:A0E4CB*
ID_OUI_FROM_DATABASE=Zyxel Communications Corporation
@@ -72791,6 +74321,9 @@ OUI:A424DD*
OUI:A4251B*
ID_OUI_FROM_DATABASE=Avaya Inc
+OUI:A42618*
+ ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+
OUI:A42940*
ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
@@ -72830,6 +74363,9 @@ OUI:A434D9*
OUI:A434F1*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:A43523*
+ ID_OUI_FROM_DATABASE=Guangdong Donyan Network Technologies Co.,Ltd.
+
OUI:A43831*
ID_OUI_FROM_DATABASE=RF elements s.r.o.
@@ -72995,6 +74531,9 @@ OUI:A4561B*
OUI:A45630*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:A456CC*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
OUI:A4580F0*
ID_OUI_FROM_DATABASE=INNOPRO
@@ -73061,6 +74600,9 @@ OUI:A46011*
OUI:A46032*
ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD
+OUI:A46191*
+ ID_OUI_FROM_DATABASE=NamJunSa
+
OUI:A462DF*
ID_OUI_FROM_DATABASE=DS Global. Co., LTD
@@ -73184,6 +74726,9 @@ OUI:A49A58*
OUI:A49B13*
ID_OUI_FROM_DATABASE=Digital Check
+OUI:A49B4F*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:A49BF5*
ID_OUI_FROM_DATABASE=Hybridserver Tec GmbH
@@ -73334,6 +74879,9 @@ OUI:A4D856*
OUI:A4D8CA*
ID_OUI_FROM_DATABASE=HONG KONG WATER WORLD TECHNOLOGY CO. LIMITED
+OUI:A4D990*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:A4D9A4*
ID_OUI_FROM_DATABASE=neXus ID Solutions AB
@@ -73418,6 +74966,9 @@ OUI:A4E4B8*
OUI:A4E597*
ID_OUI_FROM_DATABASE=Gessler GmbH
+OUI:A4E615*
+ ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
+
OUI:A4E6B1*
ID_OUI_FROM_DATABASE=Shanghai Joindata Technology Co.,Ltd.
@@ -73436,9 +74987,39 @@ OUI:A4E991*
OUI:A4E9A3*
ID_OUI_FROM_DATABASE=Honest Technology Co., Ltd
+OUI:A4EA8E*
+ ID_OUI_FROM_DATABASE=Extreme Networks, Inc.
+
OUI:A4EBD3*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:A4ED430*
+ ID_OUI_FROM_DATABASE=Sweam AB
+
+OUI:A4ED431*
+ ID_OUI_FROM_DATABASE=INGELABS S.L.
+
+OUI:A4ED434*
+ ID_OUI_FROM_DATABASE=NETAS TELEKOMUNIKASYON A.S.
+
+OUI:A4ED435*
+ ID_OUI_FROM_DATABASE=Beijing ICPC CO.,Ltd.
+
+OUI:A4ED436*
+ ID_OUI_FROM_DATABASE=Shanghai Facom Electronics Technology Co, ltd.
+
+OUI:A4ED438*
+ ID_OUI_FROM_DATABASE=Linseis Messgeraete GmbH
+
+OUI:A4ED439*
+ ID_OUI_FROM_DATABASE=Heyuan intelligence technology CO.,Ltd
+
+OUI:A4ED43A*
+ ID_OUI_FROM_DATABASE=Guangzhou Maxfaith Communication Technology Co.,LTD.
+
+OUI:A4ED43D*
+ ID_OUI_FROM_DATABASE=Brand New Brand Nordic AB
+
OUI:A4ED4E*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -73472,6 +75053,9 @@ OUI:A4FB8D*
OUI:A4FCCE*
ID_OUI_FROM_DATABASE=Security Expert Ltd.
+OUI:A8016D*
+ ID_OUI_FROM_DATABASE=Aiwa Corporation
+
OUI:A80180*
ID_OUI_FROM_DATABASE=IMAGO Technologies GmbH
@@ -73487,6 +75071,9 @@ OUI:A80C63*
OUI:A80CCA*
ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited
+OUI:A81087*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:A811FC*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -73607,6 +75194,9 @@ OUI:A8574E*
OUI:A85840*
ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
+OUI:A85AF3*
+ ID_OUI_FROM_DATABASE=Shanghai Siflower Communication Technology Co., Ltd
+
OUI:A85B6C*
ID_OUI_FROM_DATABASE=Robert Bosch Gmbh, CM-CI2
@@ -73760,6 +75350,12 @@ OUI:A898C6*
OUI:A8995C*
ID_OUI_FROM_DATABASE=aizo ag
+OUI:A89969*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
+OUI:A89A93*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:A89B10*
ID_OUI_FROM_DATABASE=inMotion Ltd.
@@ -74180,6 +75776,9 @@ OUI:AC5135*
OUI:AC51EE*
ID_OUI_FROM_DATABASE=Cambridge Communication Systems Ltd
+OUI:AC5474*
+ ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited
+
OUI:AC54EC*
ID_OUI_FROM_DATABASE=IEEE P1823 Standards Working Group
@@ -74223,7 +75822,7 @@ OUI:AC63BE*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:AC6417*
- ID_OUI_FROM_DATABASE=Siemens AG - Industrial Automation - EWA
+ ID_OUI_FROM_DATABASE=Siemens AG
OUI:AC6462*
ID_OUI_FROM_DATABASE=zte corporation
@@ -74306,6 +75905,9 @@ OUI:AC7289*
OUI:AC7409*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+OUI:AC751D*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:AC7A42*
ID_OUI_FROM_DATABASE=iConnectivity
@@ -74366,6 +75968,9 @@ OUI:AC8ACD*
OUI:AC8D14*
ID_OUI_FROM_DATABASE=Smartrove Inc
+OUI:AC9232*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:AC932F*
ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -74624,6 +76229,9 @@ OUI:ACFDEC*
OUI:B000B4*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:B0027E*
+ ID_OUI_FROM_DATABASE=MULLER SERVICES
+
OUI:B00594*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -74651,6 +76259,9 @@ OUI:B01408*
OUI:B01743*
ID_OUI_FROM_DATABASE=EDISON GLOBAL CIRCUITS LLC
+OUI:B01886*
+ ID_OUI_FROM_DATABASE=SmarDTV
+
OUI:B019C6*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -74726,6 +76337,9 @@ OUI:B02628*
OUI:B02680*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:B02A43*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
OUI:B03495*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -74930,12 +76544,18 @@ OUI:B08991*
OUI:B089C2*
ID_OUI_FROM_DATABASE=Zyptonite
+OUI:B08BCF*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:B08E1A*
ID_OUI_FROM_DATABASE=URadio Systems Co., Ltd
OUI:B09074*
ID_OUI_FROM_DATABASE=Fulan Electronics Limited
+OUI:B0907E*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:B090D4*
ID_OUI_FROM_DATABASE=Shenzhen Hoin Internet Technology Co., Ltd
@@ -75026,6 +76646,9 @@ OUI:B0B3AD*
OUI:B0B448*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:B0B867*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
OUI:B0B8D5*
ID_OUI_FROM_DATABASE=Nanjing Nengrui Auto Equipment CO.,Ltd
@@ -75038,6 +76661,9 @@ OUI:B0BD6D*
OUI:B0BDA1*
ID_OUI_FROM_DATABASE=ZAKLAD ELEKTRONICZNY SIMS
+OUI:B0BE76*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:B0BF99*
ID_OUI_FROM_DATABASE=WIZITDONGDO
@@ -75338,6 +76964,9 @@ OUI:B42CBE*
OUI:B42D56*
ID_OUI_FROM_DATABASE=Extreme Networks, Inc.
+OUI:B42E99*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+
OUI:B42EF8*
ID_OUI_FROM_DATABASE=Eline Technology co.Ltd
@@ -75446,6 +77075,51 @@ OUI:B4475E*
OUI:B44BD2*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:B44BD60*
+ ID_OUI_FROM_DATABASE=G4S Monitoring Technologies Ltd
+
+OUI:B44BD61*
+ ID_OUI_FROM_DATABASE=SHENZHEN TITA INTERACTIVE TECHNOLOGY CO.,LTD
+
+OUI:B44BD62*
+ ID_OUI_FROM_DATABASE=Shenzhen Cudy Technology Co., Ltd.
+
+OUI:B44BD63*
+ ID_OUI_FROM_DATABASE=Huizhou Sunoda Technology Co. Ltd
+
+OUI:B44BD64*
+ ID_OUI_FROM_DATABASE=Shenzhen Hi-Net Technology Co., Ltd.
+
+OUI:B44BD65*
+ ID_OUI_FROM_DATABASE=ShenZhen Comstar Technology Company
+
+OUI:B44BD66*
+ ID_OUI_FROM_DATABASE=Perspicace Intellegince Technology
+
+OUI:B44BD67*
+ ID_OUI_FROM_DATABASE=Taizhou convergence Information technology Co.,LTD
+
+OUI:B44BD68*
+ ID_OUI_FROM_DATABASE=Arnouse Digital Devices Corp
+
+OUI:B44BD69*
+ ID_OUI_FROM_DATABASE=Qstar Technology Co,Ltd
+
+OUI:B44BD6A*
+ ID_OUI_FROM_DATABASE=Shenzhen Huabai Intelligent Technology Co., Ltd.
+
+OUI:B44BD6B*
+ ID_OUI_FROM_DATABASE=DongYoung media
+
+OUI:B44BD6C*
+ ID_OUI_FROM_DATABASE=Impakt S.A.
+
+OUI:B44BD6D*
+ ID_OUI_FROM_DATABASE=ELLETA SOLUTIONS LTD
+
+OUI:B44BD6E*
+ ID_OUI_FROM_DATABASE=CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD.
+
OUI:B44CC2*
ID_OUI_FROM_DATABASE=NR ELECTRIC CO., LTD
@@ -75459,10 +77133,10 @@ OUI:B45253*
ID_OUI_FROM_DATABASE=Seagate Technology
OUI:B4527D*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:B4527E*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:B45570*
ID_OUI_FROM_DATABASE=Borea
@@ -75497,6 +77171,9 @@ OUI:B46698*
OUI:B467E9*
ID_OUI_FROM_DATABASE=Qingdao GoerTek Technology Co., Ltd.
+OUI:B46921*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:B46BFC*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -75614,6 +77291,9 @@ OUI:B4A82B*
OUI:B4A8B9*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:B4A94F*
+ ID_OUI_FROM_DATABASE=MERCURY CORPORATION
+
OUI:B4A95A*
ID_OUI_FROM_DATABASE=Avaya Inc
@@ -75692,6 +77372,9 @@ OUI:B4C799*
OUI:B4C810*
ID_OUI_FROM_DATABASE=UMPI Elettronica
+OUI:B4CB57*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
OUI:B4CCE9*
ID_OUI_FROM_DATABASE=PROSYST
@@ -75701,6 +77384,9 @@ OUI:B4CD27*
OUI:B4CEF6*
ID_OUI_FROM_DATABASE=HTC Corporation
+OUI:B4CEFE*
+ ID_OUI_FROM_DATABASE=James Czekaj
+
OUI:B4CFDB*
ID_OUI_FROM_DATABASE=Shenzhen Jiuzhou Electric Co.,LTD
@@ -75722,6 +77408,9 @@ OUI:B4D8DE*
OUI:B4DD15*
ID_OUI_FROM_DATABASE=ControlThings Oy Ab
+OUI:B4DDD0*
+ ID_OUI_FROM_DATABASE=Continental Automotive Hungary Kft
+
OUI:B4DE31*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -76016,6 +77705,12 @@ OUI:B8653B*
OUI:B869C2*
ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd.
+OUI:B869F4*
+ ID_OUI_FROM_DATABASE=Routerboard.com
+
+OUI:B86A97*
+ ID_OUI_FROM_DATABASE=Edgecore Networks Corporation
+
OUI:B86B23*
ID_OUI_FROM_DATABASE=Toshiba
@@ -76052,6 +77747,9 @@ OUI:B8797E*
OUI:B87AC9*
ID_OUI_FROM_DATABASE=Siemens Ltd.
+OUI:B87C6F*
+ ID_OUI_FROM_DATABASE=NXP (China) Management Ltd.
+
OUI:B87CF2*
ID_OUI_FROM_DATABASE=Aerohive Networks Inc.
@@ -76061,6 +77759,9 @@ OUI:B88198*
OUI:B88303*
ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+OUI:B88584*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
OUI:B88687*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -76217,6 +77918,9 @@ OUI:B8BD79*
OUI:B8BEBF*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:B8BEF4*
+ ID_OUI_FROM_DATABASE=devolo AG
+
OUI:B8BF83*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -76404,7 +78108,7 @@ OUI:B8F8BE*
ID_OUI_FROM_DATABASE=BLUECOM
OUI:B8F934*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:B8FC9A*
ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited
@@ -76532,6 +78236,9 @@ OUI:BC307D*
OUI:BC307E*
ID_OUI_FROM_DATABASE=Wistron Neweb Corporation
+OUI:BC30D9*
+ ID_OUI_FROM_DATABASE=Arcadyan Corporation
+
OUI:BC325F*
ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd.
@@ -76776,7 +78483,7 @@ OUI:BC6C21*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:BC6E64*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:BC6E76*
ID_OUI_FROM_DATABASE=Green Energy Options Ltd
@@ -76895,6 +78602,9 @@ OUI:BCA042*
OUI:BCA4E1*
ID_OUI_FROM_DATABASE=Nabto
+OUI:BCA58B*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:BCA8A6*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -76916,12 +78626,18 @@ OUI:BCADAB*
OUI:BCAEC5*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:BCAF91*
+ ID_OUI_FROM_DATABASE=TE Connectivity Sensor Solutions
+
OUI:BCB181*
ID_OUI_FROM_DATABASE=SHARP CORPORATION
OUI:BCB1F3*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:BCB22B*
+ ID_OUI_FROM_DATABASE=EM-Tech
+
OUI:BCB308*
ID_OUI_FROM_DATABASE=HONGKONG RAGENTEK COMMUNICATION TECHNOLOGY CO.,LIMITED
@@ -77003,6 +78719,9 @@ OUI:BCE09D*
OUI:BCE143*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:BCE265*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:BCE59F*
ID_OUI_FROM_DATABASE=WATERWORLD Technology Co.,LTD
@@ -77063,6 +78782,9 @@ OUI:BCFFEB*
OUI:C0028D*
ID_OUI_FROM_DATABASE=WINSTAR Display CO.,Ltd
+OUI:C00380*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:C005C2*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -77177,6 +78899,9 @@ OUI:C03F2A*
OUI:C03FD5*
ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd.
+OUI:C04004*
+ ID_OUI_FROM_DATABASE=Medicaroid Corporation
+
OUI:C041F6*
ID_OUI_FROM_DATABASE=LG ELECTRONICS INC
@@ -77192,6 +78917,9 @@ OUI:C044E3*
OUI:C048E6*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:C048FB*
+ ID_OUI_FROM_DATABASE=Shenzhen JingHanDa Electronics Co.Ltd
+
OUI:C0493D*
ID_OUI_FROM_DATABASE=MAITRISE TECHNOLOGIQUE
@@ -77273,9 +79001,57 @@ OUI:C08170*
OUI:C0830A*
ID_OUI_FROM_DATABASE=2Wire Inc
+OUI:C083590*
+ ID_OUI_FROM_DATABASE=CHONGQING JIUYU SMART TECHNOLOGY CO.LTD.
+
+OUI:C083591*
+ ID_OUI_FROM_DATABASE=Gemvax Technology ,. Co.Ltd
+
+OUI:C083592*
+ ID_OUI_FROM_DATABASE=Huaxin SM Optics Co. LTD.
+
+OUI:C083593*
+ ID_OUI_FROM_DATABASE=PCH Engineering A/S
+
+OUI:C083594*
+ ID_OUI_FROM_DATABASE=ANTS
+
+OUI:C083595*
+ ID_OUI_FROM_DATABASE=Viper Design, LLC
+
+OUI:C083596*
+ ID_OUI_FROM_DATABASE=Beijing Cloud Fly Technology Development Co.Ltd
+
+OUI:C083597*
+ ID_OUI_FROM_DATABASE=Fuzhou Fdlinker Technology Co.,LTD
+
+OUI:C083598*
+ ID_OUI_FROM_DATABASE=ista International GmbH
+
+OUI:C083599*
+ ID_OUI_FROM_DATABASE=Shenzhen Pay Device Technology Co., Ltd.
+
+OUI:C08359A*
+ ID_OUI_FROM_DATABASE=SHANGHAI CHARMHOPE INFORMATION TECHNOLOGY CO.,LTD.
+
+OUI:C08359B*
+ ID_OUI_FROM_DATABASE=Suzhou Siheng Science and Technology Ltd.
+
+OUI:C08359C*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:C08359D*
+ ID_OUI_FROM_DATABASE=Gardner Denver Thomas GmbH
+
+OUI:C08359E*
+ ID_OUI_FROM_DATABASE=Cyber Sciences, Inc.
+
OUI:C0847A*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:C0847D*
+ ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
+
OUI:C08488*
ID_OUI_FROM_DATABASE=Finis Inc
@@ -77387,6 +79163,9 @@ OUI:C0B357*
OUI:C0B658*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:C0B6F9*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:C0B713*
ID_OUI_FROM_DATABASE=Beijing Xiaoyuer Technology Co. Ltd.
@@ -77447,6 +79226,9 @@ OUI:C0D012*
OUI:C0D044*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+OUI:C0D0FF*
+ ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited
+
OUI:C0D2F3*
ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD
@@ -77654,6 +79436,9 @@ OUI:C421C8*
OUI:C4237A*
ID_OUI_FROM_DATABASE=WhizNets Inc.
+OUI:C423A2*
+ ID_OUI_FROM_DATABASE=PT. Emsonic Indonesia
+
OUI:C4242E*
ID_OUI_FROM_DATABASE=Galvanic Applied Sciences Inc
@@ -77709,7 +79494,7 @@ OUI:C43A9F*
ID_OUI_FROM_DATABASE=Siconix Inc.
OUI:C43ABE*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:C43C3C*
ID_OUI_FROM_DATABASE=CYBELEC SA
@@ -77762,9 +79547,15 @@ OUI:C44E1F*
OUI:C44EAC*
ID_OUI_FROM_DATABASE=Shenzhen Shiningworth Technology Co., Ltd.
+OUI:C44F33*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
OUI:C45006*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:C4518D*
+ ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+
OUI:C45444*
ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC.
@@ -77840,6 +79631,9 @@ OUI:C46DF1*
OUI:C46E1F*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:C46E7B*
+ ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
+
OUI:C4700B*
ID_OUI_FROM_DATABASE=GUANGZHOU CHIP TECHNOLOGIES CO.,LTD
@@ -77975,12 +79769,18 @@ OUI:C49380*
OUI:C493D9*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:C49500*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
OUI:C495A2*
ID_OUI_FROM_DATABASE=SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD
OUI:C49805*
ID_OUI_FROM_DATABASE=Minieum Networks, Inc
+OUI:C4985C*
+ ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD
+
OUI:C49880*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -78026,6 +79826,9 @@ OUI:C4B301*
OUI:C4B512*
ID_OUI_FROM_DATABASE=General Electric Digital Energy
+OUI:C4B8B4*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:C4B9CD*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -78155,6 +79958,9 @@ OUI:C4F5A5*
OUI:C4FCE4*
ID_OUI_FROM_DATABASE=DishTV NZ Ltd
+OUI:C4FEE2*
+ ID_OUI_FROM_DATABASE=AMICCOM Electronics Corporation
+
OUI:C4FF1F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -78377,6 +80183,9 @@ OUI:C850E9*
OUI:C85195*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:C8544B*
+ ID_OUI_FROM_DATABASE=Zyxel Communications Corporation
+
OUI:C85645*
ID_OUI_FROM_DATABASE=Intermas France
@@ -78620,6 +80429,9 @@ OUI:C8B5B7*
OUI:C8BA94*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
+OUI:C8BAE9*
+ ID_OUI_FROM_DATABASE=QDIS
+
OUI:C8BBD3*
ID_OUI_FROM_DATABASE=Embrane
@@ -78638,6 +80450,9 @@ OUI:C8C13C*
OUI:C8C2C6*
ID_OUI_FROM_DATABASE=Shanghai Airm2m Communication Technology Co., Ltd
+OUI:C8C2F5*
+ ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
+
OUI:C8C50E*
ID_OUI_FROM_DATABASE=Shenzhen Primestone Network Technologies.Co., Ltd.
@@ -78695,6 +80510,9 @@ OUI:C8D779*
OUI:C8D7B0*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:C8D9D2*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
OUI:C8DB26*
ID_OUI_FROM_DATABASE=Logitech
@@ -78836,6 +80654,9 @@ OUI:CC088D*
OUI:CC08E0*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:CC08FB*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:CC09C8*
ID_OUI_FROM_DATABASE=IMAQLIQ LTD
@@ -78920,6 +80741,9 @@ OUI:CC1FC4*
OUI:CC20E8*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:CC2119*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:CC2218*
ID_OUI_FROM_DATABASE=InnoDigital Co., Ltd.
@@ -79340,6 +81164,9 @@ OUI:CCC3EA*
OUI:CCC50A*
ID_OUI_FROM_DATABASE=SHENZHEN DAJIAHAO TECHNOLOGY CO.,LTD
+OUI:CCC5E5*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
OUI:CCC5EF*
ID_OUI_FROM_DATABASE=Co-Comm Servicios Telecomunicaciones S.L.
@@ -79410,7 +81237,7 @@ OUI:CCD31EB*
ID_OUI_FROM_DATABASE=Elk Products
OUI:CCD31EC*
- ID_OUI_FROM_DATABASE=Fluidic Energy
+ ID_OUI_FROM_DATABASE=NantEnergy
OUI:CCD31ED*
ID_OUI_FROM_DATABASE=CUJO LLC
@@ -79455,11 +81282,14 @@ OUI:CCEA1C*
ID_OUI_FROM_DATABASE=DCONWORKS Co., Ltd
OUI:CCEED9*
- ID_OUI_FROM_DATABASE=VAHLE DETO GmbH
+ ID_OUI_FROM_DATABASE=VAHLE Automation GmbH
OUI:CCEF48*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:CCF0FD*
+ ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd.
+
OUI:CCF3A5*
ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc
@@ -79508,6 +81338,9 @@ OUI:CCFE3C*
OUI:D0034B*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:D003DF*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:D00401*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
@@ -79547,6 +81380,9 @@ OUI:D013FD*
OUI:D0154A*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:D016B4*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:D0176A*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -79683,7 +81519,7 @@ OUI:D05099*
ID_OUI_FROM_DATABASE=ASRock Incorporation
OUI:D05162*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:D052A8*
ID_OUI_FROM_DATABASE=Physical Graph Corporation
@@ -79877,6 +81713,9 @@ OUI:D07E28*
OUI:D07E35*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:D07FA0*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:D07FC4*
ID_OUI_FROM_DATABASE=Ou Wei Technology Co.,Ltd. of Shenzhen City
@@ -80153,6 +81992,9 @@ OUI:D0EB03*
OUI:D0EB9E*
ID_OUI_FROM_DATABASE=Seowoo Inc.
+OUI:D0EFC1*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:D0F0DB*
ID_OUI_FROM_DATABASE=Ericsson
@@ -80301,7 +82143,7 @@ OUI:D437D7*
ID_OUI_FROM_DATABASE=zte corporation
OUI:D4389C*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:D43A65*
ID_OUI_FROM_DATABASE=IGRS Engineering Lab Ltd.
@@ -80412,7 +82254,7 @@ OUI:D466A8*
ID_OUI_FROM_DATABASE=Riedo Networks Ltd
OUI:D46761*
- ID_OUI_FROM_DATABASE=SAHAB TECHNOLOGY
+ ID_OUI_FROM_DATABASE=United Gulf Gate Co.
OUI:D467E7*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
@@ -80426,6 +82268,9 @@ OUI:D46867*
OUI:D468BA*
ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited
+OUI:D469A5*
+ ID_OUI_FROM_DATABASE=Miura Systems Ltd.
+
OUI:D46A6A*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -80462,6 +82307,9 @@ OUI:D47208*
OUI:D47226*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:D4741B*
+ ID_OUI_FROM_DATABASE=Beijing HuaDa ZhiBao Electronic System Co.,Ltd.
+
OUI:D476EA*
ID_OUI_FROM_DATABASE=zte corporation
@@ -80483,6 +82331,51 @@ OUI:D47B75*
OUI:D47BB0*
ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
+OUI:D47C440*
+ ID_OUI_FROM_DATABASE=Exafore Oy
+
+OUI:D47C441*
+ ID_OUI_FROM_DATABASE=Innoviz Technologies LTD
+
+OUI:D47C442*
+ ID_OUI_FROM_DATABASE=YunDing Network Technology (Beijing) Co., Ltd
+
+OUI:D47C443*
+ ID_OUI_FROM_DATABASE=OMRON SENTECH CO., LTD.
+
+OUI:D47C444*
+ ID_OUI_FROM_DATABASE=Sammi Onformation Systems
+
+OUI:D47C445*
+ ID_OUI_FROM_DATABASE=LS Communication Co.,Ltd.
+
+OUI:D47C446*
+ ID_OUI_FROM_DATABASE=ASDA ICT Co., Ltd.
+
+OUI:D47C447*
+ ID_OUI_FROM_DATABASE=Pongee Industries Co., Ltd.
+
+OUI:D47C448*
+ ID_OUI_FROM_DATABASE=Beijing Maystar Information Technology Co., Ltd.
+
+OUI:D47C449*
+ ID_OUI_FROM_DATABASE=Suzhou Wan Dian Zhang Network Technology Co., Ltd
+
+OUI:D47C44A*
+ ID_OUI_FROM_DATABASE=Tendzone International Pte Ltd
+
+OUI:D47C44B*
+ ID_OUI_FROM_DATABASE=OPTiM Corporation
+
+OUI:D47C44C*
+ ID_OUI_FROM_DATABASE=STRIVE ORTHOPEDICS INC
+
+OUI:D47C44D*
+ ID_OUI_FROM_DATABASE=Huaqin Telecom Technology Co.,Ltd.
+
+OUI:D47C44E*
+ ID_OUI_FROM_DATABASE=SHENZHEN ANYSEC TECHNOLOGY CO. LTD
+
OUI:D47DFC*
ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
@@ -80597,6 +82490,9 @@ OUI:D4A928*
OUI:D4AAFF*
ID_OUI_FROM_DATABASE=MICRO WORLD
+OUI:D4AB82*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:D4AC4E*
ID_OUI_FROM_DATABASE=BODi rS, LLC
@@ -80786,6 +82682,9 @@ OUI:D809C3*
OUI:D80CCF*
ID_OUI_FROM_DATABASE=C.G.V. S.A.S.
+OUI:D80D17*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:D80DE3*
ID_OUI_FROM_DATABASE=FXI TECHNOLOGIES AS
@@ -81050,6 +82949,9 @@ OUI:D87988*
OUI:D87CDD*
ID_OUI_FROM_DATABASE=SANIX INCORPORATED
+OUI:D87D7F*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:D87EB1*
ID_OUI_FROM_DATABASE=x.o.ware, inc.
@@ -81086,6 +82988,9 @@ OUI:D88F76*
OUI:D890E8*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:D8912A*
+ ID_OUI_FROM_DATABASE=Zyxel Communications Corporation
+
OUI:D89341*
ID_OUI_FROM_DATABASE=General Electric Global Research
@@ -81407,6 +83312,9 @@ OUI:DC15DB*
OUI:DC16A2*
ID_OUI_FROM_DATABASE=Medtronic Diabetes
+OUI:DC16B2*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:DC175A*
ID_OUI_FROM_DATABASE=Hitachi High-Technologies Corporation
@@ -81485,6 +83393,9 @@ OUI:DC3714*
OUI:DC3752*
ID_OUI_FROM_DATABASE=GE
+OUI:DC3757*
+ ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+
OUI:DC37D2*
ID_OUI_FROM_DATABASE=Hunan HKT Electronic Technology Co., Ltd
@@ -81492,7 +83403,7 @@ OUI:DC38E1*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:DC3979*
- ID_OUI_FROM_DATABASE=Skyport Systems
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:DC3A5E*
ID_OUI_FROM_DATABASE=Roku, Inc.
@@ -81515,6 +83426,9 @@ OUI:DC3EF8*
OUI:DC415F*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:DC41E5*
+ ID_OUI_FROM_DATABASE=Shenzhen Zhixin Data Service Co., Ltd.
+
OUI:DC44270*
ID_OUI_FROM_DATABASE=Suritel
@@ -81677,6 +83591,12 @@ OUI:DC85DE*
OUI:DC86D8*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:DC8B28*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:DC9088*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:DC9914*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -81947,6 +83867,12 @@ OUI:DCF090*
OUI:DCF110*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:DCF505*
+ ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+
+OUI:DCF719*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
OUI:DCF755*
ID_OUI_FROM_DATABASE=SITRONIK
@@ -81989,9 +83915,15 @@ OUI:E00DB9*
OUI:E00EDA*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+OUI:E00EE1*
+ ID_OUI_FROM_DATABASE=We Corporation Inc.
+
OUI:E0107F*
ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:E01283*
+ ID_OUI_FROM_DATABASE=Shenzhen Fanzhuo Communication Technology Co., Lt
+
OUI:E0143E*
ID_OUI_FROM_DATABASE=Modoosis Inc.
@@ -82124,6 +84056,9 @@ OUI:E048AF*
OUI:E048D3*
ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD
+OUI:E049ED*
+ ID_OUI_FROM_DATABASE=Audeze LLC
+
OUI:E04B45*
ID_OUI_FROM_DATABASE=Hi-P Electronics Pte Ltd
@@ -82175,11 +84110,17 @@ OUI:E06089*
OUI:E061B2*
ID_OUI_FROM_DATABASE=HANGZHOU ZENOINTEL TECHNOLOGY CO., LTD
+OUI:E06267*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:E06290*
ID_OUI_FROM_DATABASE=Jinan Jovision Science & Technology Co., Ltd.
+OUI:E063DA*
+ ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
+
OUI:E063E5*
- ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:E064BB*
ID_OUI_FROM_DATABASE=DigiView S.r.l.
@@ -82196,6 +84137,9 @@ OUI:E0686D*
OUI:E06995*
ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+OUI:E0735F*
+ ID_OUI_FROM_DATABASE=NUCOM
+
OUI:E0750A*
ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
@@ -82331,6 +84275,9 @@ OUI:E0AEED*
OUI:E0AF4B*
ID_OUI_FROM_DATABASE=Pluribus Networks, Inc.
+OUI:E0AF4F*
+ ID_OUI_FROM_DATABASE=Deutsche Telekom AG
+
OUI:E0B2F1*
ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED
@@ -82601,6 +84548,9 @@ OUI:E41D2D*
OUI:E41F13*
ID_OUI_FROM_DATABASE=IBM Corp
+OUI:E41FE9*
+ ID_OUI_FROM_DATABASE=Dunkermotoren GmbH
+
OUI:E422A5*
ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
@@ -82646,6 +84596,9 @@ OUI:E43022*
OUI:E432CB*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:E43493*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:E43593*
ID_OUI_FROM_DATABASE=Hangzhou GoTo technology Co.Ltd
@@ -83027,6 +84980,9 @@ OUI:E4CE70*
OUI:E4CE8F*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:E4D124*
+ ID_OUI_FROM_DATABASE=Mojo Networks, Inc.
+
OUI:E4D332*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
@@ -83039,6 +84995,9 @@ OUI:E4D53D*
OUI:E4D71D*
ID_OUI_FROM_DATABASE=Oraya Therapeutics
+OUI:E4DB6D*
+ ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd.
+
OUI:E4DD79*
ID_OUI_FROM_DATABASE=En-Vision America, Inc.
@@ -83114,6 +85073,9 @@ OUI:E4FB5D*
OUI:E4FB8F*
ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD
+OUI:E4FC82*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:E4FED9*
ID_OUI_FROM_DATABASE=EDMI Europe Ltd
@@ -83243,6 +85205,9 @@ OUI:E81863F*
OUI:E81AAC*
ID_OUI_FROM_DATABASE=ORFEO SOUNDWORKS Inc.
+OUI:E81CBA*
+ ID_OUI_FROM_DATABASE=Fortinet, Inc.
+
OUI:E81DA8*
ID_OUI_FROM_DATABASE=Ruckus Wireless
@@ -83360,6 +85325,9 @@ OUI:E85BF0*
OUI:E85D6B*
ID_OUI_FROM_DATABASE=Luminate Wireless
+OUI:E85D86*
+ ID_OUI_FROM_DATABASE=CHANG YOW TECHNOLOGIES INTERNATIONAL CO.,LTD.
+
OUI:E85E53*
ID_OUI_FROM_DATABASE=Infratec Datentechnik GmbH
@@ -83387,6 +85355,9 @@ OUI:E866C4*
OUI:E86819*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:E86A64*
+ ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd
+
OUI:E86CDA*
ID_OUI_FROM_DATABASE=Supercomputers and Neurocomputers Research Center
@@ -83501,6 +85472,9 @@ OUI:E8A364*
OUI:E8A4C1*
ID_OUI_FROM_DATABASE=Deep Sea Electronics PLC
+OUI:E8A788*
+ ID_OUI_FROM_DATABASE=XIAMEN LEELEN TECHNOLOGY CO., LTD
+
OUI:E8A7F2*
ID_OUI_FROM_DATABASE=sTraffic
@@ -83522,6 +85496,9 @@ OUI:E8B4AE*
OUI:E8B4C8*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:E8B541*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:E8B6C2*
ID_OUI_FROM_DATABASE=Juniper Networks
@@ -83555,6 +85532,9 @@ OUI:E8C229*
OUI:E8C320*
ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd
+OUI:E8C57A*
+ ID_OUI_FROM_DATABASE=Ufispace Co., LTD.
+
OUI:E8C74F*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -83807,6 +85787,9 @@ OUI:EC3586*
OUI:EC363F*
ID_OUI_FROM_DATABASE=Markov Corporation
+OUI:EC3873*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:EC388F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -83882,6 +85865,9 @@ OUI:EC542E*
OUI:EC55F9*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:EC58EA*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
OUI:EC59E7*
ID_OUI_FROM_DATABASE=Microsoft Corporation
@@ -83918,6 +85904,9 @@ OUI:EC6881*
OUI:EC6C9F*
ID_OUI_FROM_DATABASE=Chengdu Volans Technology CO.,LTD
+OUI:EC6F0B*
+ ID_OUI_FROM_DATABASE=FADU, Inc.
+
OUI:EC7097*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@@ -83927,6 +85916,9 @@ OUI:EC71DB*
OUI:EC74BA*
ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH
+OUI:EC79F2*
+ ID_OUI_FROM_DATABASE=Startel
+
OUI:EC7C74*
ID_OUI_FROM_DATABASE=Justone Technologies Co., Ltd.
@@ -83951,6 +85943,12 @@ OUI:EC8350*
OUI:EC836C*
ID_OUI_FROM_DATABASE=RM Tech Co., Ltd.
+OUI:EC83D5*
+ ID_OUI_FROM_DATABASE=GIRD Systems Inc
+
+OUI:EC84B4*
+ ID_OUI_FROM_DATABASE=CIG SHANGHAI CO LTD
+
OUI:EC852F*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -84095,6 +86093,9 @@ OUI:ECB106*
OUI:ECB1D7*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:ECB313*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
OUI:ECB541*
ID_OUI_FROM_DATABASE=SHINANO E and E Co.Ltd.
@@ -84125,6 +86126,9 @@ OUI:ECC06A*
OUI:ECC38A*
ID_OUI_FROM_DATABASE=Accuenergy (CANADA) Inc
+OUI:ECC40D*
+ ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
+
OUI:ECC882*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -84689,6 +86693,9 @@ OUI:F09E63*
OUI:F09FC2*
ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc.
+OUI:F09FFC*
+ ID_OUI_FROM_DATABASE=SHARP Corporation
+
OUI:F0A225*
ID_OUI_FROM_DATABASE=Private
@@ -84755,6 +86762,9 @@ OUI:F0AE51*
OUI:F0AF50*
ID_OUI_FROM_DATABASE=Phantom Intelligence
+OUI:F0B014*
+ ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
+
OUI:F0B052*
ID_OUI_FROM_DATABASE=Ruckus Wireless
@@ -84782,6 +86792,9 @@ OUI:F0B6EB*
OUI:F0BCC8*
ID_OUI_FROM_DATABASE=MaxID (Pty) Ltd
+OUI:F0BCC9*
+ ID_OUI_FROM_DATABASE=PFU LIMITED
+
OUI:F0BD2E*
ID_OUI_FROM_DATABASE=H+S Polatis Ltd
@@ -84848,6 +86861,9 @@ OUI:F0D767*
OUI:F0D7AA*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+OUI:F0D7DC*
+ ID_OUI_FROM_DATABASE=Wesine (Wuhan) Technology Co., Ltd.
+
OUI:F0D9B2*
ID_OUI_FROM_DATABASE=EXO S.A.
@@ -84908,6 +86924,9 @@ OUI:F0EFD2*
OUI:F0F002*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:F0F08F*
+ ID_OUI_FROM_DATABASE=Nextek Solutions Pte Ltd
+
OUI:F0F249*
ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
@@ -85217,9 +87236,15 @@ OUI:F45FF7*
OUI:F4600D*
ID_OUI_FROM_DATABASE=Panoptic Technology, Inc
+OUI:F460E2*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
OUI:F462D0*
ID_OUI_FROM_DATABASE=Not for Radio, LLC
+OUI:F4631F*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:F46349*
ID_OUI_FROM_DATABASE=Diffon Corporation
@@ -85520,6 +87545,9 @@ OUI:F4EF9E*
OUI:F4F15A*
ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:F4F197*
+ ID_OUI_FROM_DATABASE=EMTAKE Inc
+
OUI:F4F1E1*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
@@ -85736,6 +87764,9 @@ OUI:F823B2*
OUI:F82441*
ID_OUI_FROM_DATABASE=Yeelink
+OUI:F8272E*
+ ID_OUI_FROM_DATABASE=Mercku
+
OUI:F82793*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -85784,6 +87815,9 @@ OUI:F83553*
OUI:F835DD*
ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd.
+OUI:F8369B*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:F83D4E*
ID_OUI_FROM_DATABASE=Softlink Automation System Co., Ltd
@@ -85859,6 +87893,9 @@ OUI:F85C45*
OUI:F85C4D*
ID_OUI_FROM_DATABASE=Nokia
+OUI:F85E3C*
+ ID_OUI_FROM_DATABASE=SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD
+
OUI:F85F2A*
ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -86039,6 +88076,9 @@ OUI:F898B9*
OUI:F898EF*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:F89910*
+ ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+
OUI:F89955*
ID_OUI_FROM_DATABASE=Fortress Technology Inc
@@ -86192,6 +88232,9 @@ OUI:F8C96C*
OUI:F8CAB8*
ID_OUI_FROM_DATABASE=Dell Inc.
+OUI:F8CC6E*
+ ID_OUI_FROM_DATABASE=DEPO Electronics Ltd
+
OUI:F8CFC5*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
@@ -86219,6 +88262,9 @@ OUI:F8D756*
OUI:F8D7BF*
ID_OUI_FROM_DATABASE=REV Ritter GmbH
+OUI:F8D9B8*
+ ID_OUI_FROM_DATABASE=Open Mesh, Inc.
+
OUI:F8DA0C*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -86339,6 +88385,9 @@ OUI:FC019E*
OUI:FC01CD*
ID_OUI_FROM_DATABASE=FUNDACION TEKNIKER
+OUI:FC039F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:FC0647*
ID_OUI_FROM_DATABASE=Cortland Research, LLC
@@ -86555,6 +88604,9 @@ OUI:FC6018*
OUI:FC6198*
ID_OUI_FROM_DATABASE=NEC Personal Products, Ltd
+OUI:FC61E9*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
OUI:FC626E*
ID_OUI_FROM_DATABASE=Beijing MDC Telecom
@@ -86705,6 +88757,9 @@ OUI:FCAFAC*
OUI:FCB0C4*
ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd
+OUI:FCB10D*
+ ID_OUI_FROM_DATABASE=Shenzhen Tian Kun Technology Co.,LTD.
+
OUI:FCB4E6*
ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
diff --git a/hwdb/20-acpi-vendor.hwdb b/hwdb/20-acpi-vendor.hwdb
index 10b427c2cd..4207f07144 100644
--- a/hwdb/20-acpi-vendor.hwdb
+++ b/hwdb/20-acpi-vendor.hwdb
@@ -21,6 +21,9 @@ acpi:AAVA*:
acpi:AMDI*:
ID_VENDOR_FROM_DATABASE=AMD
+acpi:AMPC*:
+ ID_VENDOR_FROM_DATABASE=Ampere Computing
+
acpi:APMC*:
ID_VENDOR_FROM_DATABASE=Applied Micro Circuits Corporation
@@ -2205,6 +2208,9 @@ acpi:EHN*:
acpi:EIC*:
ID_VENDOR_FROM_DATABASE=Eicon Technology Corporation
+acpi:EIN*:
+ ID_VENDOR_FROM_DATABASE=Elegant Invention
+
acpi:EIZ*:
ID_VENDOR_FROM_DATABASE=Eizo
@@ -3123,6 +3129,9 @@ acpi:HWD*:
acpi:HWP*:
ID_VENDOR_FROM_DATABASE=Hewlett Packard
+acpi:HWV*:
+ ID_VENDOR_FROM_DATABASE=Huawei Technologies Co., Inc.
+
acpi:HXM*:
ID_VENDOR_FROM_DATABASE=Hexium Ltd.
@@ -3315,6 +3324,9 @@ acpi:IMD*:
acpi:IME*:
ID_VENDOR_FROM_DATABASE=Imagraph
+acpi:IMF*:
+ ID_VENDOR_FROM_DATABASE=Immersive Audio Technologies France
+
acpi:IMG*:
ID_VENDOR_FROM_DATABASE=IMAGENICS Co., Ltd.
@@ -3576,6 +3588,9 @@ acpi:JDI*:
acpi:JDL*:
ID_VENDOR_FROM_DATABASE=Japan Digital Laboratory Co.,Ltd.
+acpi:JEM*:
+ ID_VENDOR_FROM_DATABASE=Japan E.M.Solutions Co., Ltd.
+
acpi:JEN*:
ID_VENDOR_FROM_DATABASE=N-Vision
@@ -4011,6 +4026,9 @@ acpi:LSJ*:
acpi:LSL*:
ID_VENDOR_FROM_DATABASE=Logical Solutions
+acpi:LSP*:
+ ID_VENDOR_FROM_DATABASE=Lightspace Technologies
+
acpi:LSY*:
ID_VENDOR_FROM_DATABASE=LSI Systems Inc
@@ -5451,6 +5469,9 @@ acpi:PXL*:
acpi:PXM*:
ID_VENDOR_FROM_DATABASE=Proxim Inc
+acpi:PXN*:
+ ID_VENDOR_FROM_DATABASE=PixelNext Inc
+
acpi:QCC*:
ID_VENDOR_FROM_DATABASE=QuakeCom Company Ltd
@@ -5472,6 +5493,9 @@ acpi:QCP*:
acpi:QDI*:
ID_VENDOR_FROM_DATABASE=Quantum Data Incorporated
+acpi:QDL*:
+ ID_VENDOR_FROM_DATABASE=QD Laser, Inc.
+
acpi:QDM*:
ID_VENDOR_FROM_DATABASE=Quadram
@@ -6132,6 +6156,9 @@ acpi:SNS*:
acpi:SNT*:
ID_VENDOR_FROM_DATABASE=SuperNet Inc
+acpi:SNV*:
+ ID_VENDOR_FROM_DATABASE=SONOVE GmbH
+
acpi:SNW*:
ID_VENDOR_FROM_DATABASE=Snell & Wilcox
@@ -6381,6 +6408,9 @@ acpi:SXD*:
acpi:SXG*:
ID_VENDOR_FROM_DATABASE=SELEX GALILEO
+acpi:SXI*:
+ ID_VENDOR_FROM_DATABASE=Silex Inside
+
acpi:SXL*:
ID_VENDOR_FROM_DATABASE=SolutionInside
@@ -6819,6 +6849,9 @@ acpi:TST*:
acpi:TSV*:
ID_VENDOR_FROM_DATABASE=TRANSVIDEO
+acpi:TSW*:
+ ID_VENDOR_FROM_DATABASE=VRSHOW Technology Limited
+
acpi:TSY*:
ID_VENDOR_FROM_DATABASE=TouchSystems
@@ -7197,6 +7230,9 @@ acpi:VRM*:
acpi:VRS*:
ID_VENDOR_FROM_DATABASE=VRstudios, Inc.
+acpi:VRT*:
+ ID_VENDOR_FROM_DATABASE=Varjo Technologies
+
acpi:VSC*:
ID_VENDOR_FROM_DATABASE=ViewSonic Corporation
diff --git a/hwdb/20-acpi-vendor.hwdb.patch b/hwdb/20-acpi-vendor.hwdb.patch
index f344b48246..308d1353d4 100644
--- a/hwdb/20-acpi-vendor.hwdb.patch
+++ b/hwdb/20-acpi-vendor.hwdb.patch
@@ -1,5 +1,5 @@
---- 20-acpi-vendor.hwdb.base 2018-03-02 11:56:07.871144120 +0100
-+++ 20-acpi-vendor.hwdb 2018-03-02 11:56:07.886144208 +0100
+--- 20-acpi-vendor.hwdb.base 2018-06-12 15:51:50.897235123 +0200
++++ 20-acpi-vendor.hwdb 2018-06-12 15:51:50.907235139 +0200
@@ -3,6 +3,8 @@
# Data imported from:
# http://www.uefi.org/uefi-pnp-export
@@ -19,7 +19,7 @@
acpi:AMDI*:
ID_VENDOR_FROM_DATABASE=AMD
-@@ -250,6 +249,9 @@
+@@ -253,6 +252,9 @@
acpi:AAA*:
ID_VENDOR_FROM_DATABASE=Avolites Ltd
@@ -29,7 +29,7 @@
acpi:AAE*:
ID_VENDOR_FROM_DATABASE=Anatek Electronics Inc.
-@@ -277,6 +279,9 @@
+@@ -280,6 +282,9 @@
acpi:ABO*:
ID_VENDOR_FROM_DATABASE=D-Link Systems Inc
@@ -39,7 +39,7 @@
acpi:ABS*:
ID_VENDOR_FROM_DATABASE=Abaco Systems, Inc.
-@@ -322,7 +327,7 @@
+@@ -325,7 +330,7 @@
acpi:ACO*:
ID_VENDOR_FROM_DATABASE=Allion Computer Inc.
@@ -48,7 +48,7 @@
ID_VENDOR_FROM_DATABASE=Aspen Tech Inc
acpi:ACR*:
-@@ -592,6 +597,9 @@
+@@ -595,6 +600,9 @@
acpi:AMT*:
ID_VENDOR_FROM_DATABASE=AMT International Industry
@@ -58,7 +58,7 @@
acpi:AMX*:
ID_VENDOR_FROM_DATABASE=AMX LLC
-@@ -640,6 +648,9 @@
+@@ -643,6 +651,9 @@
acpi:AOA*:
ID_VENDOR_FROM_DATABASE=AOpen Inc.
@@ -68,7 +68,7 @@
acpi:AOE*:
ID_VENDOR_FROM_DATABASE=Advanced Optics Electronics, Inc.
-@@ -649,6 +660,9 @@
+@@ -652,6 +663,9 @@
acpi:AOT*:
ID_VENDOR_FROM_DATABASE=Alcatel
@@ -78,7 +78,7 @@
acpi:APC*:
ID_VENDOR_FROM_DATABASE=American Power Conversion
-@@ -824,7 +838,7 @@
+@@ -827,7 +841,7 @@
ID_VENDOR_FROM_DATABASE=Alps Electric Inc
acpi:AUO*:
@@ -87,7 +87,7 @@
acpi:AUR*:
ID_VENDOR_FROM_DATABASE=Aureal Semiconductor
-@@ -904,6 +918,9 @@
+@@ -907,6 +921,9 @@
acpi:AXE*:
ID_VENDOR_FROM_DATABASE=Axell Corporation
@@ -97,7 +97,7 @@
acpi:AXI*:
ID_VENDOR_FROM_DATABASE=American Magnetics
-@@ -1051,6 +1068,9 @@
+@@ -1054,6 +1071,9 @@
acpi:BML*:
ID_VENDOR_FROM_DATABASE=BIOMED Lab
@@ -107,7 +107,7 @@
acpi:BMS*:
ID_VENDOR_FROM_DATABASE=BIOMEDISYS
-@@ -1063,6 +1083,9 @@
+@@ -1066,6 +1086,9 @@
acpi:BNO*:
ID_VENDOR_FROM_DATABASE=Bang & Olufsen
@@ -117,7 +117,7 @@
acpi:BNS*:
ID_VENDOR_FROM_DATABASE=Boulder Nonlinear Systems
-@@ -1303,6 +1326,9 @@
+@@ -1306,6 +1329,9 @@
acpi:CHA*:
ID_VENDOR_FROM_DATABASE=Chase Research PLC
@@ -127,7 +127,7 @@
acpi:CHD*:
ID_VENDOR_FROM_DATABASE=ChangHong Electric Co.,Ltd
-@@ -1453,6 +1479,9 @@
+@@ -1456,6 +1482,9 @@
acpi:COD*:
ID_VENDOR_FROM_DATABASE=CODAN Pty. Ltd.
@@ -137,7 +137,7 @@
acpi:COI*:
ID_VENDOR_FROM_DATABASE=Codec Inc.
-@@ -1856,7 +1885,7 @@
+@@ -1859,7 +1888,7 @@
ID_VENDOR_FROM_DATABASE=Dragon Information Technology
acpi:DJE*:
@@ -146,9 +146,9 @@
acpi:DJP*:
ID_VENDOR_FROM_DATABASE=Maygay Machines, Ltd
-@@ -2176,6 +2205,9 @@
- acpi:EIC*:
- ID_VENDOR_FROM_DATABASE=Eicon Technology Corporation
+@@ -2182,6 +2211,9 @@
+ acpi:EIN*:
+ ID_VENDOR_FROM_DATABASE=Elegant Invention
+acpi:EIZ*:
+ ID_VENDOR_FROM_DATABASE=Eizo
@@ -156,7 +156,7 @@
acpi:EKA*:
ID_VENDOR_FROM_DATABASE=MagTek Inc.
-@@ -2434,6 +2466,9 @@
+@@ -2440,6 +2472,9 @@
acpi:FCG*:
ID_VENDOR_FROM_DATABASE=First International Computer Ltd
@@ -166,7 +166,7 @@
acpi:FCS*:
ID_VENDOR_FROM_DATABASE=Focus Enhancements, Inc.
-@@ -2902,6 +2937,9 @@
+@@ -2908,6 +2943,9 @@
acpi:HEC*:
ID_VENDOR_FROM_DATABASE=Hisense Electric Co., Ltd.
@@ -176,7 +176,7 @@
acpi:HEL*:
ID_VENDOR_FROM_DATABASE=Hitachi Micro Systems Europe Ltd
-@@ -3031,6 +3069,9 @@
+@@ -3037,6 +3075,9 @@
acpi:HSD*:
ID_VENDOR_FROM_DATABASE=HannStar Display Corp
@@ -186,7 +186,7 @@
acpi:HSM*:
ID_VENDOR_FROM_DATABASE=AT&T Microelectronics
-@@ -3151,6 +3192,9 @@
+@@ -3160,6 +3201,9 @@
acpi:ICI*:
ID_VENDOR_FROM_DATABASE=Infotek Communication Inc
@@ -196,7 +196,7 @@
acpi:ICM*:
ID_VENDOR_FROM_DATABASE=Intracom SA
-@@ -3244,6 +3288,9 @@
+@@ -3253,6 +3297,9 @@
acpi:IKE*:
ID_VENDOR_FROM_DATABASE=Ikegami Tsushinki Co. Ltd.
@@ -206,7 +206,7 @@
acpi:IKS*:
ID_VENDOR_FROM_DATABASE=Ikos Systems Inc
-@@ -3286,6 +3333,9 @@
+@@ -3298,6 +3345,9 @@
acpi:IMT*:
ID_VENDOR_FROM_DATABASE=Inmax Technology Corporation
@@ -216,7 +216,7 @@
acpi:INA*:
ID_VENDOR_FROM_DATABASE=Inventec Corporation
-@@ -3787,6 +3837,9 @@
+@@ -3802,6 +3852,9 @@
acpi:LAN*:
ID_VENDOR_FROM_DATABASE=Sodeman Lancom Inc
@@ -226,7 +226,7 @@
acpi:LAS*:
ID_VENDOR_FROM_DATABASE=LASAT Comm. A/S
-@@ -3832,6 +3885,9 @@
+@@ -3847,6 +3900,9 @@
acpi:LED*:
ID_VENDOR_FROM_DATABASE=Long Engineering Design Inc
@@ -236,7 +236,7 @@
acpi:LEG*:
ID_VENDOR_FROM_DATABASE=Legerity, Inc
-@@ -3847,6 +3903,9 @@
+@@ -3862,6 +3918,9 @@
acpi:LGC*:
ID_VENDOR_FROM_DATABASE=Logic Ltd
@@ -246,7 +246,7 @@
acpi:LGI*:
ID_VENDOR_FROM_DATABASE=Logitech Inc
-@@ -3898,6 +3957,9 @@
+@@ -3913,6 +3972,9 @@
acpi:LND*:
ID_VENDOR_FROM_DATABASE=Land Computer Company Ltd
@@ -256,7 +256,7 @@
acpi:LNK*:
ID_VENDOR_FROM_DATABASE=Link Tech Inc
-@@ -3932,7 +3994,7 @@
+@@ -3947,7 +4009,7 @@
ID_VENDOR_FROM_DATABASE=Design Technology
acpi:LPL*:
@@ -265,7 +265,7 @@
acpi:LSC*:
ID_VENDOR_FROM_DATABASE=LifeSize Communications
-@@ -4102,6 +4164,9 @@
+@@ -4120,6 +4182,9 @@
acpi:MCX*:
ID_VENDOR_FROM_DATABASE=Millson Custom Solutions Inc.
@@ -275,7 +275,7 @@
acpi:MDA*:
ID_VENDOR_FROM_DATABASE=Media4 Inc
-@@ -4333,6 +4398,9 @@
+@@ -4351,6 +4416,9 @@
acpi:MOM*:
ID_VENDOR_FROM_DATABASE=Momentum Data Systems
@@ -285,7 +285,7 @@
acpi:MOS*:
ID_VENDOR_FROM_DATABASE=Moses Corporation
-@@ -4558,6 +4626,9 @@
+@@ -4576,6 +4644,9 @@
acpi:NAL*:
ID_VENDOR_FROM_DATABASE=Network Alchemy
@@ -295,7 +295,7 @@
acpi:NAT*:
ID_VENDOR_FROM_DATABASE=NaturalPoint Inc.
-@@ -5062,6 +5133,9 @@
+@@ -5080,6 +5151,9 @@
acpi:PCX*:
ID_VENDOR_FROM_DATABASE=PC Xperten
@@ -305,7 +305,7 @@
acpi:PDM*:
ID_VENDOR_FROM_DATABASE=Psion Dacom Plc.
-@@ -5125,9 +5199,6 @@
+@@ -5143,9 +5217,6 @@
acpi:PHE*:
ID_VENDOR_FROM_DATABASE=Philips Medical Systems Boeblingen GmbH
@@ -315,7 +315,7 @@
acpi:PHL*:
ID_VENDOR_FROM_DATABASE=Philips Consumer Electronics Company
-@@ -5212,9 +5283,6 @@
+@@ -5230,9 +5301,6 @@
acpi:PNL*:
ID_VENDOR_FROM_DATABASE=Panelview, Inc.
@@ -325,7 +325,7 @@
acpi:PNR*:
ID_VENDOR_FROM_DATABASE=Planar Systems, Inc.
-@@ -5350,15 +5418,9 @@
+@@ -5368,15 +5436,9 @@
acpi:PTS*:
ID_VENDOR_FROM_DATABASE=Plain Tree Systems Inc
@@ -341,7 +341,7 @@
acpi:PVG*:
ID_VENDOR_FROM_DATABASE=Proview Global Co., Ltd
-@@ -5665,9 +5727,6 @@
+@@ -5689,9 +5751,6 @@
acpi:RTI*:
ID_VENDOR_FROM_DATABASE=Rancho Tech Inc
@@ -351,7 +351,7 @@
acpi:RTL*:
ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Company Ltd
-@@ -5830,9 +5889,6 @@
+@@ -5854,9 +5913,6 @@
acpi:SEE*:
ID_VENDOR_FROM_DATABASE=SeeColor Corporation
@@ -361,7 +361,7 @@
acpi:SEI*:
ID_VENDOR_FROM_DATABASE=Seitz & Associates Inc
-@@ -6283,6 +6339,9 @@
+@@ -6310,6 +6366,9 @@
acpi:SVD*:
ID_VENDOR_FROM_DATABASE=SVD Computer
@@ -371,7 +371,7 @@
acpi:SVI*:
ID_VENDOR_FROM_DATABASE=Sun Microsystems
-@@ -6364,6 +6423,9 @@
+@@ -6394,6 +6453,9 @@
acpi:SZM*:
ID_VENDOR_FROM_DATABASE=Shenzhen MTC Co., Ltd
@@ -381,7 +381,7 @@
acpi:TAA*:
ID_VENDOR_FROM_DATABASE=Tandberg
-@@ -6454,6 +6516,9 @@
+@@ -6484,6 +6546,9 @@
acpi:TDG*:
ID_VENDOR_FROM_DATABASE=Six15 Technologies
@@ -391,7 +391,7 @@
acpi:TDM*:
ID_VENDOR_FROM_DATABASE=Tandem Computer Europe Inc
-@@ -6496,6 +6561,9 @@
+@@ -6526,6 +6591,9 @@
acpi:TEV*:
ID_VENDOR_FROM_DATABASE=Televés, S.A.
@@ -401,7 +401,7 @@
acpi:TEZ*:
ID_VENDOR_FROM_DATABASE=Tech Source Inc.
-@@ -6610,9 +6678,6 @@
+@@ -6640,9 +6708,6 @@
acpi:TNC*:
ID_VENDOR_FROM_DATABASE=TNC Industrial Company Ltd
@@ -411,7 +411,7 @@
acpi:TNM*:
ID_VENDOR_FROM_DATABASE=TECNIMAGEN SA
-@@ -6916,14 +6981,14 @@
+@@ -6949,14 +7014,14 @@
acpi:UNC*:
ID_VENDOR_FROM_DATABASE=Unisys Corporation
@@ -432,7 +432,7 @@
acpi:UNI*:
ID_VENDOR_FROM_DATABASE=Uniform Industry Corp.
-@@ -6958,6 +7023,9 @@
+@@ -6991,6 +7056,9 @@
acpi:USA*:
ID_VENDOR_FROM_DATABASE=Utimaco Safeware AG
@@ -442,7 +442,7 @@
acpi:USD*:
ID_VENDOR_FROM_DATABASE=U.S. Digital Corporation
-@@ -7192,9 +7260,6 @@
+@@ -7228,9 +7296,6 @@
acpi:WAL*:
ID_VENDOR_FROM_DATABASE=Wave Access
@@ -452,7 +452,7 @@
acpi:WAV*:
ID_VENDOR_FROM_DATABASE=Wavephore
-@@ -7313,7 +7378,7 @@
+@@ -7349,7 +7414,7 @@
ID_VENDOR_FROM_DATABASE=Woxter Technology Co. Ltd
acpi:WYS*:
@@ -461,7 +461,7 @@
acpi:WYT*:
ID_VENDOR_FROM_DATABASE=Wooyoung Image & Information Co.,Ltd.
-@@ -7327,9 +7392,6 @@
+@@ -7363,9 +7428,6 @@
acpi:XDM*:
ID_VENDOR_FROM_DATABASE=XDM Ltd.
@@ -471,7 +471,7 @@
acpi:XES*:
ID_VENDOR_FROM_DATABASE=Extreme Engineering Solutions, Inc.
-@@ -7360,9 +7422,6 @@
+@@ -7396,9 +7458,6 @@
acpi:XNT*:
ID_VENDOR_FROM_DATABASE=XN Technologies, Inc.
@@ -481,7 +481,7 @@
acpi:XQU*:
ID_VENDOR_FROM_DATABASE=SHANGHAI SVA-DAV ELECTRONICS CO., LTD
-@@ -7429,6 +7488,9 @@
+@@ -7465,6 +7524,9 @@
acpi:ZBX*:
ID_VENDOR_FROM_DATABASE=Zebax Technologies
diff --git a/hwdb/20-pci-classes.hwdb b/hwdb/20-pci-classes.hwdb
index 3c0c465e5f..c994679c37 100644
--- a/hwdb/20-pci-classes.hwdb
+++ b/hwdb/20-pci-classes.hwdb
@@ -20,6 +20,30 @@ pci:v*d*sv*sd*bc01sc00*
pci:v*d*sv*sd*bc01sc01*
ID_PCI_SUBCLASS_FROM_DATABASE=IDE interface
+pci:v*d*sv*sd*bc01sc01i00*
+ ID_PCI_INTERFACE_FROM_DATABASE=ISA Compatibility mode-only controller
+
+pci:v*d*sv*sd*bc01sc01i05*
+ ID_PCI_INTERFACE_FROM_DATABASE=PCI native mode-only controller
+
+pci:v*d*sv*sd*bc01sc01i0A*
+ ID_PCI_INTERFACE_FROM_DATABASE=ISA Compatibility mode controller, supports both channels switched to PCI native mode
+
+pci:v*d*sv*sd*bc01sc01i0F*
+ ID_PCI_INTERFACE_FROM_DATABASE=PCI native mode controller, supports both channels switched to ISA compatibility mode
+
+pci:v*d*sv*sd*bc01sc01i80*
+ ID_PCI_INTERFACE_FROM_DATABASE=ISA Compatibility mode-only controller, supports bus mastering
+
+pci:v*d*sv*sd*bc01sc01i85*
+ ID_PCI_INTERFACE_FROM_DATABASE=PCI native mode-only controller, supports bus mastering
+
+pci:v*d*sv*sd*bc01sc01i8A*
+ ID_PCI_INTERFACE_FROM_DATABASE=ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering
+
+pci:v*d*sv*sd*bc01sc01i8F*
+ ID_PCI_INTERFACE_FROM_DATABASE=PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering
+
pci:v*d*sv*sd*bc01sc02*
ID_PCI_SUBCLASS_FROM_DATABASE=Floppy disk controller
@@ -462,7 +486,16 @@ pci:v*d*sv*sd*bc0Csc06*
ID_PCI_SUBCLASS_FROM_DATABASE=InfiniBand
pci:v*d*sv*sd*bc0Csc07*
- ID_PCI_SUBCLASS_FROM_DATABASE=IPMI SMIC interface
+ ID_PCI_SUBCLASS_FROM_DATABASE=IPMI Interface
+
+pci:v*d*sv*sd*bc0Csc07i00*
+ ID_PCI_INTERFACE_FROM_DATABASE=SMIC
+
+pci:v*d*sv*sd*bc0Csc07i01*
+ ID_PCI_INTERFACE_FROM_DATABASE=KCS
+
+pci:v*d*sv*sd*bc0Csc07i02*
+ ID_PCI_INTERFACE_FROM_DATABASE=BT (Block Transfer)
pci:v*d*sv*sd*bc0Csc08*
ID_PCI_SUBCLASS_FROM_DATABASE=SERCOS interface
diff --git a/hwdb/20-pci-vendor-model.hwdb b/hwdb/20-pci-vendor-model.hwdb
index 5b2a494e26..94e495c280 100644
--- a/hwdb/20-pci-vendor-model.hwdb
+++ b/hwdb/20-pci-vendor-model.hwdb
@@ -11,6 +11,60 @@ pci:v00000010*
pci:v00000010d00008139*
ID_MODEL_FROM_DATABASE=AT-2500TX V3 Ethernet
+pci:v00000014*
+ ID_VENDOR_FROM_DATABASE=Loongson Technology LLC
+
+pci:v00000014d00007A00*
+ ID_MODEL_FROM_DATABASE=Hyper Transport Bridge Controller
+
+pci:v00000014d00007A02*
+ ID_MODEL_FROM_DATABASE=APB (Advanced Peripheral Bus) Controller
+
+pci:v00000014d00007A03*
+ ID_MODEL_FROM_DATABASE=Gigabit Ethernet Controller
+
+pci:v00000014d00007A04*
+ ID_MODEL_FROM_DATABASE=OTG USB Controller
+
+pci:v00000014d00007A05*
+ ID_MODEL_FROM_DATABASE=Vivante GPU (Graphics Processing Unit)
+
+pci:v00000014d00007A06*
+ ID_MODEL_FROM_DATABASE=DC (Display Controller)
+
+pci:v00000014d00007A07*
+ ID_MODEL_FROM_DATABASE=HDA (High Definition Audio) Controller
+
+pci:v00000014d00007A08*
+ ID_MODEL_FROM_DATABASE=SATA AHCI Controller
+
+pci:v00000014d00007A09*
+ ID_MODEL_FROM_DATABASE=PCI-to-PCI Bridge
+
+pci:v00000014d00007A0B*
+ ID_MODEL_FROM_DATABASE=SPI Controller
+
+pci:v00000014d00007A0C*
+ ID_MODEL_FROM_DATABASE=LPC Controller
+
+pci:v00000014d00007A0F*
+ ID_MODEL_FROM_DATABASE=DMA (Direct Memory Access) Controller
+
+pci:v00000014d00007A14*
+ ID_MODEL_FROM_DATABASE=EHCI USB Controller
+
+pci:v00000014d00007A15*
+ ID_MODEL_FROM_DATABASE=Vivante GPU (Graphics Processing Unit)
+
+pci:v00000014d00007A19*
+ ID_MODEL_FROM_DATABASE=PCI-to-PCI Bridge
+
+pci:v00000014d00007A24*
+ ID_MODEL_FROM_DATABASE=OHCI USB Controller
+
+pci:v00000014d00007A29*
+ ID_MODEL_FROM_DATABASE=PCI-to-PCI Bridge
+
pci:v0000001C*
ID_VENDOR_FROM_DATABASE=PEAK-System Technik GmbH
@@ -104,6 +158,9 @@ pci:v00000432*
pci:v00000432d00000001*
ID_MODEL_FROM_DATABASE=Pluto2 DVB-T Receiver for PCMCIA [EasyWatch MobilSet]
+pci:v00000497*
+ ID_VENDOR_FROM_DATABASE=Dell Inc. (wrong ID)
+
pci:v00000675*
ID_VENDOR_FROM_DATABASE=Dynalink
@@ -1139,6 +1196,9 @@ pci:v00001000d0000005Dsv000017AAsd00001053*
pci:v00001000d0000005Dsv00001D49sd00000600*
ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkSystem RAID 730-8i 1GB Cache PCIe 12Gb Adapter)
+pci:v00001000d0000005Dsv00001D49sd00000609*
+ ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkSystem RAID 730-8i 4GB Flash PCIe 12Gb Adapter)
+
pci:v00001000d0000005Dsv00008086sd0000351E*
ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (RMS3CC080 RAID Controller)
@@ -2166,16 +2226,16 @@ pci:v00001002d0000131D*
ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6 Graphics]
pci:v00001002d000015DD*
- ID_MODEL_FROM_DATABASE=Raven Bridge [Radeon Vega Series / Radeon Vega Mobile Series]
+ ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series]
pci:v00001002d000015DDsv0000103Csd000083C6*
- ID_MODEL_FROM_DATABASE=Raven Bridge [Radeon Vega Series / Radeon Vega Mobile Series] (Radeon Vega 8 Mobile)
+ ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] (Radeon Vega 8 Mobile)
pci:v00001002d000015DDsv00001458sd0000D000*
- ID_MODEL_FROM_DATABASE=Raven Bridge [Radeon Vega Series / Radeon Vega Mobile Series] (Radeon RX Vega 11)
+ ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] (Radeon RX Vega 11)
pci:v00001002d000015FF*
- ID_MODEL_FROM_DATABASE=Vega [Radeon Vega 28 Mobile]
+ ID_MODEL_FROM_DATABASE=Vega 11 [Radeon Vega 28 Mobile]
pci:v00001002d00001714*
ID_MODEL_FROM_DATABASE=BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series]
@@ -2448,7 +2508,7 @@ pci:v00001002d00004354*
ID_MODEL_FROM_DATABASE=215CT [Mach64 CT PCI]
pci:v00001002d00004358*
- ID_MODEL_FROM_DATABASE=210888CX [Mach64 CX]
+ ID_MODEL_FROM_DATABASE=Mach64 CX [Graphics Xpression]
pci:v00001002d00004361*
ID_MODEL_FROM_DATABASE=IXP SB300 AC'97 Audio Controller
@@ -3051,61 +3111,61 @@ pci:v00001002d00004654*
ID_MODEL_FROM_DATABASE=Mach64 VT
pci:v00001002d00004742*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X]
pci:v00001002d00004742sv00001002sd00000040*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00001002sd00000044*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00001002sd00000061*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro AIW AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro AIW AGP 2X)
pci:v00001002d00004742sv00001002sd00000062*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro AIW AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro AIW AGP 2X)
pci:v00001002d00004742sv00001002sd00000063*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro AIW AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro AIW AGP 2X)
pci:v00001002d00004742sv00001002sd00000080*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00001002sd00000084*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00001002sd00004742*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00001002sd00008001*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00001028sd00000082*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00001028sd00004082*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Optiplex GX1 Onboard Display Adapter)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Optiplex GX1 Onboard Display Adapter)
pci:v00001002d00004742sv00001028sd00008082*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00001028sd0000C082*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004742sv00008086sd00004152*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Xpert 98D AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Xpert 98D AGP 2X)
pci:v00001002d00004742sv00008086sd0000464A*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 2X (Rage Pro Turbo AGP 2X)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X)
pci:v00001002d00004744*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 1X
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 1X]
pci:v00001002d00004744sv00001002sd00004744*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 1X (Rage Pro Turbo AGP)
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 1X] (Rage Pro Turbo AGP)
pci:v00001002d00004744sv00008086sd00004D55*
- ID_MODEL_FROM_DATABASE=3D Rage PRO AGP 1X (Rage 3D Pro AGP 1X [Intel MU440EX])
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 1X] (Rage 3D Pro AGP 1X [Intel MU440EX])
pci:v00001002d00004749*
ID_MODEL_FROM_DATABASE=3D Rage PRO PCI
@@ -3171,64 +3231,64 @@ pci:v00001002d00004750sv00001002sd00004750*
ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo)
pci:v00001002d00004752*
- ID_MODEL_FROM_DATABASE=Rage XL PCI
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI]
pci:v00001002d00004752sv00000E11sd0000001E*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (Proliant Rage XL)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Proliant Rage XL)
pci:v00001002d00004752sv00001002sd00000008*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (Rage XL)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Rage XL)
pci:v00001002d00004752sv00001002sd00004752*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (Proliant Rage XL)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Proliant Rage XL)
pci:v00001002d00004752sv00001002sd00008008*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (Rage XL)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Rage XL)
pci:v00001002d00004752sv00001014sd00000240*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (eServer xSeries server mainboard)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (eServer xSeries server mainboard)
pci:v00001002d00004752sv00001028sd000000CE*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 1400)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 1400)
pci:v00001002d00004752sv00001028sd000000D1*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 2550)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 2550)
pci:v00001002d00004752sv00001028sd000000D9*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 2500)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 2500)
pci:v00001002d00004752sv00001028sd00000134*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 600SC)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 600SC)
pci:v00001002d00004752sv00001028sd0000014A*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 1750)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 1750)
pci:v00001002d00004752sv00001028sd00000165*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (PowerEdge 750)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 750)
pci:v00001002d00004752sv0000103Csd000010E1*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (NetServer Rage XL)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (NetServer Rage XL)
pci:v00001002d00004752sv0000103Csd00003208*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (ProLiant DL140 G2)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (ProLiant DL140 G2)
pci:v00001002d00004752sv0000107Bsd00006400*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (6400 Server)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (6400 Server)
pci:v00001002d00004752sv00001734sd0000007A*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (PRIMERGY RX/TX series onboard VGA)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PRIMERGY RX/TX series onboard VGA)
pci:v00001002d00004752sv00001734sd00001073*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (Primergy Econel 200 D2020 mainboard)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Primergy Econel 200 D2020 mainboard)
pci:v00001002d00004752sv00008086sd00003411*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (SDS2 Mainboard)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (SDS2 Mainboard)
pci:v00001002d00004752sv00008086sd00003427*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (S875WP1-E mainboard)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (S875WP1-E mainboard)
pci:v00001002d00004752sv00008086sd00005744*
- ID_MODEL_FROM_DATABASE=Rage XL PCI (S845WD1-E mainboard)
+ ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (S845WD1-E mainboard)
pci:v00001002d00004753*
ID_MODEL_FROM_DATABASE=Rage XC
@@ -3237,43 +3297,43 @@ pci:v00001002d00004753sv00001002sd00004753*
ID_MODEL_FROM_DATABASE=Rage XC
pci:v00001002d00004754*
- ID_MODEL_FROM_DATABASE=3D Rage II/II+ PCI [Mach64 GT]
+ ID_MODEL_FROM_DATABASE=Mach64 GT/GT-B [3D Rage I/II]
pci:v00001002d00004755*
- ID_MODEL_FROM_DATABASE=Mach64 GTB [3D Rage II+ DVD]
+ ID_MODEL_FROM_DATABASE=Mach64 GT-B [3D Rage II+ DVD]
pci:v00001002d00004756*
- ID_MODEL_FROM_DATABASE=3D Rage IIC PCI [Mach64 GT IIC]
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC PCI]
pci:v00001002d00004756sv00001002sd00004756*
- ID_MODEL_FROM_DATABASE=3D Rage IIC PCI [Mach64 GT IIC] (Rage IIC)
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC PCI] (Rage IIC)
pci:v00001002d00004757*
- ID_MODEL_FROM_DATABASE=3D Rage IIC AGP
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP]
pci:v00001002d00004757sv00001002sd00004757*
- ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage IIC AGP)
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage IIC AGP)
pci:v00001002d00004757sv00001028sd00000089*
- ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC)
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage 3D IIC)
pci:v00001002d00004757sv00001028sd0000008E*
- ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (PowerEdge 1300 onboard video)
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (PowerEdge 1300 onboard video)
pci:v00001002d00004757sv00001028sd00004082*
- ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC)
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage 3D IIC)
pci:v00001002d00004757sv00001028sd00008082*
- ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC)
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage 3D IIC)
pci:v00001002d00004757sv00001028sd0000C082*
- ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC)
+ ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage 3D IIC)
pci:v00001002d00004758*
- ID_MODEL_FROM_DATABASE=210888GX [Mach64 GX PCI]
+ ID_MODEL_FROM_DATABASE=Mach64 GX [WinTurbo]
pci:v00001002d00004759*
- ID_MODEL_FROM_DATABASE=3D Rage IIC PCI
+ ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage IIC PCI]
pci:v00001002d0000475A*
ID_MODEL_FROM_DATABASE=3D Rage IIC AGP
@@ -3381,31 +3441,31 @@ pci:v00001002d00004B6C*
ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT Platinum Edition AGP] (Secondary)
pci:v00001002d00004C42*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP]
pci:v00001002d00004C42sv00000E11sd0000B0E7*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro (Compaq Presario 5240))
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro (Compaq Presario 5240))
pci:v00001002d00004C42sv00000E11sd0000B0E8*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage 3D LT Pro)
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage 3D LT Pro)
pci:v00001002d00004C42sv00000E11sd0000B10E*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (3D Rage LT Pro (Compaq Armada 1750))
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (3D Rage LT Pro (Compaq Armada 1750))
pci:v00001002d00004C42sv00001002sd00000040*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro AGP 2X)
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro AGP 2X)
pci:v00001002d00004C42sv00001002sd00000044*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro AGP 2X)
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro AGP 2X)
pci:v00001002d00004C42sv00001002sd00004C42*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro AGP 2X)
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro AGP 2X)
pci:v00001002d00004C42sv00001002sd00008001*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage LT Pro AGP 2X)
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro AGP 2X)
pci:v00001002d00004C42sv00001028sd00000085*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO AGP 2X (Rage 3D LT Pro)
+ ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage 3D LT Pro)
pci:v00001002d00004C46*
ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3
@@ -3465,16 +3525,16 @@ pci:v00001002d00004C4Dsv000013BDsd00001019*
ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (PC-AR10)
pci:v00001002d00004C50*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI
+ ID_MODEL_FROM_DATABASE=Rage 3 LT [3D Rage LT PRO PCI]
pci:v00001002d00004C50sv00001002sd00004C50*
- ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro)
+ ID_MODEL_FROM_DATABASE=Rage 3 LT [3D Rage LT PRO PCI] (Rage LT Pro)
pci:v00001002d00004C52*
- ID_MODEL_FROM_DATABASE=Rage Mobility-M1 PCI
+ ID_MODEL_FROM_DATABASE=M1 [Rage Mobility-M1 PCI]
pci:v00001002d00004C52sv00001033sd00008112*
- ID_MODEL_FROM_DATABASE=Rage Mobility-M1 PCI (Versa Note VXi)
+ ID_MODEL_FROM_DATABASE=M1 [Rage Mobility-M1 PCI] (Versa Note VXi)
pci:v00001002d00004C54*
ID_MODEL_FROM_DATABASE=264LT [Mach64 LT]
@@ -3675,34 +3735,34 @@ pci:v00001002d00005044sv00001002sd00000029*
ID_MODEL_FROM_DATABASE=All-In-Wonder 128 PCI (Rage 128 AIW)
pci:v00001002d00005046*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS]
pci:v00001002d00005046sv00001002sd00000004*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro)
pci:v00001002d00005046sv00001002sd00000008*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro/Xpert 2000 Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro/Xpert 2000 Pro)
pci:v00001002d00005046sv00001002sd00000014*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro)
pci:v00001002d00005046sv00001002sd00000018*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro/Xpert 2000 Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro/Xpert 2000 Pro)
pci:v00001002d00005046sv00001002sd00000028*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage 128 Pro AIW AGP)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage 128 Pro AIW AGP)
pci:v00001002d00005046sv00001002sd0000002A*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage 128 Pro AIW AGP)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage 128 Pro AIW AGP)
pci:v00001002d00005046sv00001002sd00000048*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury Pro)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro)
pci:v00001002d00005046sv00001002sd00002000*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury MAXX AGP 4x (TMDS) (VGA device))
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury MAXX AGP 4x (TMDS) (VGA device))
pci:v00001002d00005046sv00001002sd00002001*
- ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4x TMDS (Rage Fury MAXX AGP 4x (TMDS) (Extra device?!))
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury MAXX AGP 4x (TMDS) (Extra device?!))
pci:v00001002d00005050*
ID_MODEL_FROM_DATABASE=Rage128 [Xpert 128 PCI]
@@ -3972,25 +4032,25 @@ pci:v00001002d00005245sv00001002sd00000068*
ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Rage 128 AIW)
pci:v00001002d00005246*
- ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP]
pci:v00001002d00005246sv00001002sd00000004*
- ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Magnum/Xpert 128/Xpert 99)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP] (Magnum/Xpert 128/Xpert 99)
pci:v00001002d00005246sv00001002sd00000008*
- ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Magnum/Xpert128/X99/Xpert2000)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP] (Magnum/Xpert128/X99/Xpert2000)
pci:v00001002d00005246sv00001002sd00000028*
- ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Rage 128 AIW AGP)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP] (Rage 128 AIW AGP)
pci:v00001002d00005246sv00001002sd00000044*
- ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Rage Fury/Xpert 128/Xpert 2000)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP] (Rage Fury/Xpert 128/Xpert 2000)
pci:v00001002d00005246sv00001002sd00000068*
- ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Rage 128 AIW AGP)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP] (Rage 128 AIW AGP)
pci:v00001002d00005246sv00001002sd00000448*
- ID_MODEL_FROM_DATABASE=Rage Fury/Xpert 128/Xpert 2000 AGP 2x (Rage Fury)
+ ID_MODEL_FROM_DATABASE=Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP] (Rage Fury)
pci:v00001002d0000524B*
ID_MODEL_FROM_DATABASE=Rage 128 VR PCI
@@ -4146,16 +4206,16 @@ pci:v00001002d00005653sv0000103Csd00000940*
ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] (Compaq NW8240 Mobile Workstation)
pci:v00001002d00005654*
- ID_MODEL_FROM_DATABASE=264VT [Mach64 VT]
+ ID_MODEL_FROM_DATABASE=Mach64 VT [Video Xpression]
pci:v00001002d00005654sv00001002sd00005654*
- ID_MODEL_FROM_DATABASE=264VT [Mach64 VT] (Mach64VT Reference)
+ ID_MODEL_FROM_DATABASE=Mach64 VT [Video Xpression] (Mach64VT Reference)
pci:v00001002d00005655*
ID_MODEL_FROM_DATABASE=264VT3 [Mach64 VT3]
pci:v00001002d00005656*
- ID_MODEL_FROM_DATABASE=264VT4 [Mach64 VT4]
+ ID_MODEL_FROM_DATABASE=Mach64 VT4 [Video Xpression+]
pci:v00001002d00005657*
ID_MODEL_FROM_DATABASE=RV410 [Radeon X550 XTX / X700]
@@ -4712,6 +4772,9 @@ pci:v00001002d00006603*
pci:v00001002d00006604*
ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465]
+pci:v00001002d00006604sv00001025sd00000776*
+ ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465] (Aspire V5 Radeon R7 M265)
+
pci:v00001002d00006604sv0000103Csd00008006*
ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465] (FirePro M4170)
@@ -4979,6 +5042,24 @@ pci:v00001002d00006667*
pci:v00001002d0000666F*
ID_MODEL_FROM_DATABASE=Sun LE [Radeon HD 8550M / R5 M230]
+pci:v00001002d000066A0*
+ ID_MODEL_FROM_DATABASE=Vega 20 [Radeon Instinct]
+
+pci:v00001002d000066A1*
+ ID_MODEL_FROM_DATABASE=Vega 20
+
+pci:v00001002d000066A2*
+ ID_MODEL_FROM_DATABASE=Vega 20
+
+pci:v00001002d000066A3*
+ ID_MODEL_FROM_DATABASE=Vega 20
+
+pci:v00001002d000066A7*
+ ID_MODEL_FROM_DATABASE=Vega 20
+
+pci:v00001002d000066AF*
+ ID_MODEL_FROM_DATABASE=Vega 20
+
pci:v00001002d00006704*
ID_MODEL_FROM_DATABASE=Cayman PRO GL [FirePro V7900]
@@ -6768,64 +6849,91 @@ pci:v00001002d000067D0*
ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro V7300X / V7350x2]
pci:v00001002d000067DF*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580]
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X]
pci:v00001002d000067DFsv00001002sd00000B37*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 480)
+
+pci:v00001002d000067DFsv00001028sd00001722*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 570X)
+
+pci:v00001002d000067DFsv00001028sd00001723*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 580X)
pci:v00001002d000067DFsv00001043sd000004A8*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 480)
pci:v00001002d000067DFsv00001043sd000004B0*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 470)
pci:v00001002d000067DFsv00001043sd000004FB*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 480)
pci:v00001002d000067DFsv00001043sd000004FD*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480 8GB)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 480 8GB)
+
+pci:v00001002d000067DFsv0000106Bsd00000161*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon Pro 580)
+
+pci:v00001002d000067DFsv0000106Bsd00000162*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon Pro 575)
+
+pci:v00001002d000067DFsv0000106Bsd00000163*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon Pro 570)
pci:v00001002d000067DFsv00001458sd000022F0*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 570)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 570)
+
+pci:v00001002d000067DFsv00001458sd000022F7*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 570 Gaming 4G)
pci:v00001002d000067DFsv00001462sd00003411*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 470)
pci:v00001002d000067DFsv00001462sd00003413*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 480)
+
+pci:v00001002d000067DFsv00001462sd00003416*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 570)
+
+pci:v00001002d000067DFsv00001462sd00003418*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 580 Armor 4G OC)
pci:v00001002d000067DFsv0000148Csd00002372*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 480)
pci:v00001002d000067DFsv0000148Csd00002373*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 470)
pci:v00001002d000067DFsv00001682sd00009470*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 470)
pci:v00001002d000067DFsv00001682sd00009480*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 480)
pci:v00001002d000067DFsv00001682sd00009588*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 580 XTR)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 580 XTR)
pci:v00001002d000067DFsv0000174Bsd0000E347*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470/480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 470/480)
pci:v00001002d000067DFsv0000174Bsd0000E349*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 470)
pci:v00001002d000067DFsv00001787sd0000A470*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 470)
pci:v00001002d000067DFsv00001787sd0000A480*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Radeon RX 480)
+
+pci:v00001002d000067DFsv00001849sd00005001*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Phantom Gaming X RX 580 OC)
pci:v00001002d000067DFsv00001DA2sd0000E353*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Sapphire Radeon RX 580 Pulse 8GB)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Sapphire Radeon RX 580 Pulse 8GB)
pci:v00001002d000067DFsv00001DA2sd0000E366*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Nitro+ Radeon RX 580 4GB)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X] (Nitro+ Radeon RX 580 4GB)
pci:v00001002d000067E0*
ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4170]
@@ -6876,49 +6984,61 @@ pci:v00001002d000067EB*
ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro V5300X]
pci:v00001002d000067EF*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/560]
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560]
pci:v00001002d000067EFsv0000106Bsd00000160*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/560] (Radeon Pro 460)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560] (Radeon Pro 460)
pci:v00001002d000067EFsv0000106Bsd00000166*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/560] (Radeon Pro 455)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560] (Radeon Pro 455)
pci:v00001002d000067EFsv0000106Bsd00000167*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/560] (Radeon Pro 450)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560] (Radeon Pro 450)
pci:v00001002d000067EFsv0000106Bsd00000179*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/560] (Radeon Pro 560)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560] (Radeon Pro 560)
+
+pci:v00001002d000067EFsv0000106Bsd0000017A*
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560] (Radeon Pro 555)
pci:v00001002d000067EFsv00001642sd00001727*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/560] (Polaris 21 XL [Radeon RX 560D])
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560] (Polaris 21 XL [Radeon RX 560D])
pci:v00001002d000067EFsv00001682sd0000956D*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/560] (Polaris 21 XL [Radeon RX 560D])
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560] (Polaris 21 XL [Radeon RX 560D])
pci:v00001002d000067FF*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560]
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X]
pci:v00001002d000067FFsv00001002sd00000B04*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560] (Radeon RX 560)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560)
+
+pci:v00001002d000067FFsv00001028sd00001721*
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560X)
+
+pci:v00001002d000067FFsv00001028sd00001726*
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560DX)
+
+pci:v00001002d000067FFsv0000103Csd00008479*
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560X Mobile)
pci:v00001002d000067FFsv00001043sd000004BC*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560] (Radeon RX 560)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560)
pci:v00001002d000067FFsv00001458sd000022ED*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560] (Radeon RX 560)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560)
pci:v00001002d000067FFsv0000148Csd00002381*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560] (Radeon RX 560)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560)
pci:v00001002d000067FFsv00001682sd00009560*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560] (Radeon RX 560)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560)
pci:v00001002d000067FFsv00001DA2sd0000E348*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560] (Radeon RX 560)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560)
pci:v00001002d000067FFsv00001DA2sd0000E367*
- ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560] (Radeon RX 550 640SP)
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 550 640SP)
pci:v00001002d00006800*
ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M]
@@ -8178,22 +8298,22 @@ pci:v00001002d000068C1sv000017AAsd00003977*
ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M)
pci:v00001002d000068C7*
- ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A]
+ ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A]
pci:v00001002d000068C7sv00001462sd00002241*
- ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570)
+ ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570)
pci:v00001002d000068C7sv00001462sd00002243*
- ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570)
+ ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570)
pci:v00001002d000068C7sv00001462sd00002244*
- ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570)
+ ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570)
pci:v00001002d000068C7sv00001462sd00002245*
- ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Radeon HD 6550A)
+ ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Radeon HD 6550A)
pci:v00001002d000068C7sv00001462sd00002246*
- ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A] (Radeon HD 6550A)
+ ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Radeon HD 6550A)
pci:v00001002d000068C8*
ID_MODEL_FROM_DATABASE=Redwood XT GL [FirePro V4800]
@@ -9120,13 +9240,31 @@ pci:v00001002d00006995*
ID_MODEL_FROM_DATABASE=Lexa XT [Radeon PRO WX 2100]
pci:v00001002d0000699F*
- ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon RX 550]
+ ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon RX 550/550X]
+
+pci:v00001002d0000699Fsv00001028sd00001720*
+ ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon RX 550/550X] (Radeon RX 550X)
pci:v00001002d0000699Fsv0000148Csd00002380*
- ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon RX 550] (Lexa XL [Radeon RX 550])
+ ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon RX 550/550X] (Lexa XL [Radeon RX 550])
pci:v00001002d0000699Fsv00001DA2sd0000E367*
- ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon RX 550]
+ ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon RX 550/550X] (Lexa PRO [Radeon RX 550])
+
+pci:v00001002d000069A0*
+ ID_MODEL_FROM_DATABASE=Vega 12
+
+pci:v00001002d000069A1*
+ ID_MODEL_FROM_DATABASE=Vega 12
+
+pci:v00001002d000069A2*
+ ID_MODEL_FROM_DATABASE=Vega 12
+
+pci:v00001002d000069A3*
+ ID_MODEL_FROM_DATABASE=Vega 12
+
+pci:v00001002d000069AF*
+ ID_MODEL_FROM_DATABASE=Vega 12
pci:v00001002d0000700F*
ID_MODEL_FROM_DATABASE=RS100 AGP Bridge
@@ -9954,7 +10092,7 @@ pci:v00001002d00009553sv00001025sd0000017D*
ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570)
pci:v00001002d00009553sv00001025sd00000205*
- ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570)
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570 / 545v)
pci:v00001002d00009553sv00001025sd00000206*
ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570)
@@ -9963,11 +10101,17 @@ pci:v00001002d00009553sv00001025sd00000237*
ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570)
pci:v00001002d00009553sv00001028sd000002BE*
- ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570)
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570 / 545v)
pci:v00001002d00009553sv00001028sd000002E8*
ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530)
+pci:v00001002d00009553sv0000103Csd0000143C*
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v)
+
+pci:v00001002d00009553sv0000103Csd00001446*
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v)
+
pci:v00001002d00009553sv0000103Csd00003624*
ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530)
@@ -9989,6 +10133,24 @@ pci:v00001002d00009553sv0000104Dsd00009056*
pci:v00001002d00009553sv00001179sd0000FF82*
ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Satellite L505-13T GPU (Mobility Radeon HD 5145))
+pci:v00001002d00009553sv0000144Dsd0000C07F*
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v)
+
+pci:v00001002d00009553sv0000144Dsd0000C571*
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v)
+
+pci:v00001002d00009553sv00001462sd00001006*
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v)
+
+pci:v00001002d00009553sv000017AAsd00002129*
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v)
+
+pci:v00001002d00009553sv000017AAsd0000215B*
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v)
+
+pci:v00001002d00009553sv000017AAsd000021BB*
+ ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v)
+
pci:v00001002d00009555*
ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4350/4550]
@@ -10388,6 +10550,9 @@ pci:v00001002d00009874sv000017AAsd00005116*
pci:v00001002d00009874sv000017AAsd00005118*
ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R5 Graphics)
+pci:v00001002d000098E4*
+ ID_MODEL_FROM_DATABASE=Stoney [Radeon R2/R3/R4/R5 Graphics]
+
pci:v00001002d00009900*
ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660G]
@@ -14087,6 +14252,9 @@ pci:v0000102Bd00002527sv0000102Bsd00000F84*
pci:v0000102Bd00002527sv0000102Bsd00001E41*
ID_MODEL_FROM_DATABASE=Millennium G550
+pci:v0000102Bd00002527sv0000102Bsd000022C0*
+ ID_MODEL_FROM_DATABASE=Millennium G550 (G550 PCIe)
+
pci:v0000102Bd00002527sv0000102Bsd00002300*
ID_MODEL_FROM_DATABASE=Millennium G550 (LP PCIE)
@@ -15773,6 +15941,9 @@ pci:v0000103Cd00004031*
pci:v0000103Cd00004037*
ID_MODEL_FROM_DATABASE=PCIe Local Bus Adapter
+pci:v0000103Cd00009602*
+ ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx)
+
pci:v0000103E*
ID_VENDOR_FROM_DATABASE=Solliday Engineering
@@ -17283,7 +17454,7 @@ pci:v00001054d0000350E*
ID_MODEL_FROM_DATABASE=SH7751R PCI Controller (PCIC)
pci:v00001055*
- ID_VENDOR_FROM_DATABASE=Efar Microsystems
+ ID_VENDOR_FROM_DATABASE=Microchip Technology / SMSC
pci:v00001055d00009130*
ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] IDE
@@ -18554,12 +18725,18 @@ pci:v00001077d00001644sv00001077sd0000E4F8*
pci:v00001077d00001654*
ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 50GbE Controller
+pci:v00001077d00001654sv00001077sd00000032*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 50GbE Controller (QL45212 Flex 50Gb 2-port Ethernet Adapter)
+
pci:v00001077d00001654sv00001590sd00000223*
ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 50GbE Controller (Synergy 6810C 25/50Gb Ethernet Adapter)
pci:v00001077d00001656*
ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller
+pci:v00001077d00001656sv00001077sd00000033*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (QL45214 Flex 25Gb 4-port Ethernet Adapter)
+
pci:v00001077d00001656sv00001077sd000002A7*
ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (QL45212-DE 25GbE Adapter)
@@ -18572,6 +18749,9 @@ pci:v00001077d00001656sv00001077sd0000E4F7*
pci:v00001077d0000165C*
ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE)
+pci:v00001077d0000165Csv00001077sd00000034*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) (QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE)
+
pci:v00001077d0000165Csv00001077sd0000E4F1*
ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) (FastLinQ QL45462H 40GbE FCoE Adapter)
@@ -18581,6 +18761,9 @@ pci:v00001077d0000165Csv00001077sd0000E4F2*
pci:v00001077d0000165E*
ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI)
+pci:v00001077d0000165Esv00001077sd00000034*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) (QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE)
+
pci:v00001077d0000165Esv00001077sd0000E4F1*
ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) (FastLinQ QL45462H 40GbE iSCSI Adapter)
@@ -18872,6 +19055,9 @@ pci:v00001077d00008070sv00001077sd00000001*
pci:v00001077d00008070sv00001077sd00000002*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GE 2P QL41112HxCU-DE Adapter)
+pci:v00001077d00008070sv00001077sd00000004*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (4x10GE QL41164HFCU CNA)
+
pci:v00001077d00008070sv00001077sd00000005*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic 4x10GE QL41164HMRJ CNA)
@@ -18888,11 +19074,17 @@ pci:v00001077d00008070sv00001077sd0000000B*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (25GE 2P QL41262HxCU-DE Adapter)
pci:v00001077d00008070sv00001077sd00000011*
- ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FastLinQ QL41212H 25GbE Adapter)
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FastLinQ QL41212HLCU 25GbE Adapter)
pci:v00001077d00008070sv00001077sd00000012*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FastLinQ QL41112H 10GbE Adapter)
+pci:v00001077d00008070sv00001077sd00000019*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QL41232HOCU - Dual Port 25/10GbE SFP28 OCP Adapter)
+
+pci:v00001077d00008070sv00001077sd00000039*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic QL41262 PCIe 25Gb 2-Port SFP28 Ethernet Adapter)
+
pci:v00001077d00008070sv00001590sd0000021D*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10/25GbE 2P QL41222HLCU-HP Adapter)
@@ -18914,6 +19106,9 @@ pci:v00001077d00008080sv00001077sd00000001*
pci:v00001077d00008080sv00001077sd00000002*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (10GE 2P QL41112HxCU-DE Adapter)
+pci:v00001077d00008080sv00001077sd00000004*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (4x10GE QL41164HFCU CNA)
+
pci:v00001077d00008080sv00001077sd00000005*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (QLogic 4x10GE QL41164HMRJ CNA)
@@ -18947,6 +19142,12 @@ pci:v00001077d00008084sv00001077sd00000001*
pci:v00001077d00008084sv00001077sd00000002*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (10GE 2P QL41112HxCU-DE Adapter)
+pci:v00001077d00008084sv00001077sd00000003*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (4x10GE QL41164HxRJ CNA)
+
+pci:v00001077d00008084sv00001077sd00000004*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (4x10GE QL41164HFCU CNA)
+
pci:v00001077d00008084sv00001077sd00000005*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (QLogic 4x10GE QL41164HMRJ CNA)
@@ -18980,6 +19181,12 @@ pci:v00001077d00008090sv00001077sd00000001*
pci:v00001077d00008090sv00001077sd00000002*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (10GE 2P QL41112HxCU-DE Adapter)
+pci:v00001077d00008090sv00001077sd00000003*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (4x10GE QL41164HxRJ CNA)
+
+pci:v00001077d00008090sv00001077sd00000004*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (4x10GE QL41164HFCU CNA)
+
pci:v00001077d00008090sv00001077sd00000005*
ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 4x10GE QL41164HMRJ CNA)
@@ -24639,10 +24846,16 @@ pci:v000010DE*
ID_VENDOR_FROM_DATABASE=NVIDIA Corporation
pci:v000010DEd00000008*
- ID_MODEL_FROM_DATABASE=NV1 [EDGE 3D]
+ ID_MODEL_FROM_DATABASE=NV1 [STG2000X-B Series]
pci:v000010DEd00000009*
- ID_MODEL_FROM_DATABASE=NV1 [EDGE 3D]
+ ID_MODEL_FROM_DATABASE=NV1 [NV1 Series]
+
+pci:v000010DEd00000018*
+ ID_MODEL_FROM_DATABASE=NV3 [Riva 128]
+
+pci:v000010DEd00000019*
+ ID_MODEL_FROM_DATABASE=NV3 [Riva 128ZX]
pci:v000010DEd00000020*
ID_MODEL_FROM_DATABASE=NV4 [Riva TNT]
@@ -25449,10 +25662,10 @@ pci:v000010DEd0000009D*
ID_MODEL_FROM_DATABASE=G70GL [Quadro FX 4500]
pci:v000010DEd000000A0*
- ID_MODEL_FROM_DATABASE=NV5 [Aladdin TNT2]
+ ID_MODEL_FROM_DATABASE=NV0A [Aladdin TNT2 IGP]
pci:v000010DEd000000A0sv000014AFsd00005810*
- ID_MODEL_FROM_DATABASE=NV5 [Aladdin TNT2] (Maxi Gamer Xentor)
+ ID_MODEL_FROM_DATABASE=NV0A [Aladdin TNT2 IGP] (Maxi Gamer Xentor)
pci:v000010DEd000000C0*
ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800 GS]
@@ -25737,7 +25950,7 @@ pci:v000010DEd000000F6sv00001682sd0000217E*
ID_MODEL_FROM_DATABASE=NV43 [GeForce 6800 GS/XT] (XFX GeForce 6800 XTreme 256MB DDR3 AGP)
pci:v000010DEd000000F8*
- ID_MODEL_FROM_DATABASE=NV40GL [Quadro FX 3400/4400]
+ ID_MODEL_FROM_DATABASE=NV45GL [Quadro FX 3400/4400]
pci:v000010DEd000000F9*
ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT/GTO/Ultra]
@@ -25749,10 +25962,10 @@ pci:v000010DEd000000F9sv00001682sd00002120*
ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT/GTO/Ultra] (GEFORCE 6800 GT PCI-E)
pci:v000010DEd000000FA*
- ID_MODEL_FROM_DATABASE=NV36 [GeForce PCX 5750]
+ ID_MODEL_FROM_DATABASE=NV39 [GeForce PCX 5750]
pci:v000010DEd000000FB*
- ID_MODEL_FROM_DATABASE=NV38 [GeForce PCX 5900]
+ ID_MODEL_FROM_DATABASE=NV35 [GeForce PCX 5900]
pci:v000010DEd000000FC*
ID_MODEL_FROM_DATABASE=NV37GL [Quadro FX 330/GeForce PCX 5300]
@@ -25764,7 +25977,7 @@ pci:v000010DEd000000FE*
ID_MODEL_FROM_DATABASE=NV38GL [Quadro FX 1300]
pci:v000010DEd000000FF*
- ID_MODEL_FROM_DATABASE=NV18 [GeForce PCX 4300]
+ ID_MODEL_FROM_DATABASE=NV19 [GeForce PCX 4300]
pci:v000010DEd00000100*
ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR]
@@ -29376,7 +29589,7 @@ pci:v000010DEd00000864*
ID_MODEL_FROM_DATABASE=C79 [GeForce 9300]
pci:v000010DEd00000865*
- ID_MODEL_FROM_DATABASE=C79 [GeForce 9300/ION]
+ ID_MODEL_FROM_DATABASE=C79 [GeForce 9300 / ION]
pci:v000010DEd00000866*
ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M G]
@@ -29448,22 +29661,22 @@ pci:v000010DEd00000874*
ID_MODEL_FROM_DATABASE=C79 [ION]
pci:v000010DEd00000876*
- ID_MODEL_FROM_DATABASE=ION VGA [GeForce 9400M]
+ ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M / ION]
pci:v000010DEd0000087A*
ID_MODEL_FROM_DATABASE=C79 [GeForce 9400]
pci:v000010DEd0000087D*
- ID_MODEL_FROM_DATABASE=ION VGA
+ ID_MODEL_FROM_DATABASE=C79 [ION]
pci:v000010DEd0000087Dsv000019DAsd0000A123*
- ID_MODEL_FROM_DATABASE=ION VGA (IONITX-F-E)
+ ID_MODEL_FROM_DATABASE=C79 [ION] (IONITX-F-E)
pci:v000010DEd0000087E*
- ID_MODEL_FROM_DATABASE=ION LE VGA
+ ID_MODEL_FROM_DATABASE=C79 [ION LE]
pci:v000010DEd0000087F*
- ID_MODEL_FROM_DATABASE=ION LE VGA
+ ID_MODEL_FROM_DATABASE=C79 [ION LE]
pci:v000010DEd000008A0*
ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M]
@@ -29555,6 +29768,9 @@ pci:v000010DEd00000A65*
pci:v000010DEd00000A65sv00001043sd00008334*
ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] (EN210 SILENT)
+pci:v000010DEd00000A65sv00001458sd000036A9*
+ ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] (GV-N210D3-1GI (rev. 6.0/6.1))
+
pci:v000010DEd00000A65sv00001462sd00008094*
ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] (N210 [Geforce 210] PCIe graphics adapter)
@@ -29586,7 +29802,7 @@ pci:v000010DEd00000A6E*
ID_MODEL_FROM_DATABASE=GT218M [GeForce 305M]
pci:v000010DEd00000A6F*
- ID_MODEL_FROM_DATABASE=GT218 [ION]
+ ID_MODEL_FROM_DATABASE=GT218M [ION]
pci:v000010DEd00000A70*
ID_MODEL_FROM_DATABASE=GT218M [GeForce 310M]
@@ -29610,7 +29826,7 @@ pci:v000010DEd00000A75*
ID_MODEL_FROM_DATABASE=GT218M [GeForce 310M]
pci:v000010DEd00000A76*
- ID_MODEL_FROM_DATABASE=GT218 [ION 2]
+ ID_MODEL_FROM_DATABASE=GT218M [ION 2]
pci:v000010DEd00000A78*
ID_MODEL_FROM_DATABASE=GT218GL [Quadro FX 380 LP]
@@ -30422,6 +30638,9 @@ pci:v000010DEd00000FC1*
pci:v000010DEd00000FC2*
ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 630 OEM]
+pci:v000010DEd00000FC5*
+ ID_MODEL_FROM_DATABASE=GK107
+
pci:v000010DEd00000FC6*
ID_MODEL_FROM_DATABASE=GK107 [GeForce GTX 650]
@@ -30713,6 +30932,9 @@ pci:v000010DEd00001040sv00001043sd000083A0*
pci:v000010DEd00001042*
ID_MODEL_FROM_DATABASE=GF119 [GeForce 510]
+pci:v000010DEd00001045*
+ ID_MODEL_FROM_DATABASE=GF119
+
pci:v000010DEd00001048*
ID_MODEL_FROM_DATABASE=GF119 [GeForce 605]
@@ -32084,6 +32306,9 @@ pci:v000010DEd000011B7*
pci:v000010DEd000011B8*
ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K5100M]
+pci:v000010DEd000011B9*
+ ID_MODEL_FROM_DATABASE=GK104GLM
+
pci:v000010DEd000011BA*
ID_MODEL_FROM_DATABASE=GK104GL [Quadro K5000]
@@ -32333,6 +32558,9 @@ pci:v000010DEd00001289*
pci:v000010DEd0000128B*
ID_MODEL_FROM_DATABASE=GK208B [GeForce GT 710]
+pci:v000010DEd0000128Bsv00001043sd000085F7*
+ ID_MODEL_FROM_DATABASE=GK208B [GeForce GT 710] (GT710-SL-1GD5)
+
pci:v000010DEd00001290*
ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M]
@@ -32768,6 +32996,9 @@ pci:v000010DEd00001B02*
pci:v000010DEd00001B06*
ID_MODEL_FROM_DATABASE=GP102 [GeForce GTX 1080 Ti]
+pci:v000010DEd00001B07*
+ ID_MODEL_FROM_DATABASE=GP102 [P102-100]
+
pci:v000010DEd00001B30*
ID_MODEL_FROM_DATABASE=GP102GL [Quadro P6000]
@@ -32790,7 +33021,7 @@ pci:v000010DEd00001B82*
ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1070 Ti]
pci:v000010DEd00001B83*
- ID_MODEL_FROM_DATABASE=GP104
+ ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1060 6GB]
pci:v000010DEd00001B84*
ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1060 3GB]
@@ -32846,6 +33077,12 @@ pci:v000010DEd00001BB7sv00001462sd000011E9*
pci:v000010DEd00001BB8*
ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P3000 Mobile]
+pci:v000010DEd00001BB9*
+ ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P4200 Mobile]
+
+pci:v000010DEd00001BBB*
+ ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P3200 Mobile]
+
pci:v000010DEd00001BC7*
ID_MODEL_FROM_DATABASE=GP104 [P104-101]
@@ -32919,7 +33156,7 @@ pci:v000010DEd00001C70*
ID_MODEL_FROM_DATABASE=GP106GL
pci:v000010DEd00001C80*
- ID_MODEL_FROM_DATABASE=GP107
+ ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050 3GB]
pci:v000010DEd00001C81*
ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050]
@@ -32957,23 +33194,53 @@ pci:v000010DEd00001CB3*
pci:v000010DEd00001CB6*
ID_MODEL_FROM_DATABASE=GP107GL [Quadro P620]
+pci:v000010DEd00001CBA*
+ ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P2000 Mobile]
+
+pci:v000010DEd00001CBB*
+ ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P1000 Mobile]
+
+pci:v000010DEd00001CBC*
+ ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P600 Mobile]
+
pci:v000010DEd00001D01*
ID_MODEL_FROM_DATABASE=GP108 [GeForce GT 1030]
pci:v000010DEd00001D10*
ID_MODEL_FROM_DATABASE=GP108M [GeForce MX150]
+pci:v000010DEd00001D12*
+ ID_MODEL_FROM_DATABASE=GP108M [GeForce MX150]
+
+pci:v000010DEd00001D12sv00001D72sd00001701*
+ ID_MODEL_FROM_DATABASE=GP108M [GeForce MX150] (Mi Notebook Pro [GeForce MX150])
+
pci:v000010DEd00001D33*
- ID_MODEL_FROM_DATABASE=GP108GL [Quadro P500]
+ ID_MODEL_FROM_DATABASE=GP108GLM [Quadro P500 Mobile]
pci:v000010DEd00001D81*
ID_MODEL_FROM_DATABASE=GV100 [TITAN V]
pci:v000010DEd00001DB1*
- ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 SXM2]
+ ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 SXM2 16GB]
+
+pci:v000010DEd00001DB3*
+ ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 FHHL 16GB]
pci:v000010DEd00001DB4*
- ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 PCIe]
+ ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 PCIe 16GB]
+
+pci:v000010DEd00001DB5*
+ ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 SXM2 32GB]
+
+pci:v000010DEd00001DB6*
+ ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 PCIe 32GB]
+
+pci:v000010DEd00001DB7*
+ ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 DGXS 32GB]
+
+pci:v000010DEd00001DBA*
+ ID_MODEL_FROM_DATABASE=GV100GL [Quadro GV100]
pci:v000010DF*
ID_VENDOR_FROM_DATABASE=Emulex Corporation
@@ -37053,7 +37320,7 @@ pci:v0000111Cd00000001*
ID_MODEL_FROM_DATABASE=Powerbis Bridge
pci:v0000111D*
- ID_VENDOR_FROM_DATABASE=Integrated Device Technology, Inc. [IDT]
+ ID_VENDOR_FROM_DATABASE=Microsemi / PMC / IDT
pci:v0000111Dd00000001*
ID_MODEL_FROM_DATABASE=IDT77201/77211 155Mbps ATM SAR Controller [NICStAR]
@@ -37068,7 +37335,7 @@ pci:v0000111Dd00000005*
ID_MODEL_FROM_DATABASE=IDT77V222 155Mbps ATM MICRO ABR SAR Controller
pci:v0000111Dd00008018*
- ID_MODEL_FROM_DATABASE=PES12N3A PCI Express Switch
+ ID_MODEL_FROM_DATABASE=PES12N3A 12-lane 3-Port PCI Express Switch
pci:v0000111Dd0000801C*
ID_MODEL_FROM_DATABASE=PES24N3A PCI Express Switch
@@ -37214,11 +37481,23 @@ pci:v0000111Dd00008088sv00001093sd00007600*
pci:v0000111Dd00008088sv00001093sd00007602*
ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8384)
+pci:v0000111Dd0000808A*
+ ID_MODEL_FROM_DATABASE=89HPES32NT24BG2 PCI Express Switch
+
+pci:v0000111Dd0000808C*
+ ID_MODEL_FROM_DATABASE=89HPES32NT24AG2 PCI Express Switch
+
pci:v0000111Dd0000808E*
ID_MODEL_FROM_DATABASE=PES24NT24G2 PCI Express Switch
pci:v0000111Dd0000808F*
- ID_MODEL_FROM_DATABASE=PES32NT8AG2
+ ID_MODEL_FROM_DATABASE=89HPES32NT8AG2 32-Lane 8-Port PCIe Gen2 System Interconnect Switch with Non-Transparent Bridging
+
+pci:v0000111Dd00008090*
+ ID_MODEL_FROM_DATABASE=89HPES16NT16G2 16-Lane 16-Port PCIe Gen2 System Interconnect Switch
+
+pci:v0000111Dd00008092*
+ ID_MODEL_FROM_DATABASE=89HPES12NT12G2 12-Lane 12-Port PCIe Gen2 System Interconnect Switch
pci:v0000111Dd000080CF*
ID_MODEL_FROM_DATABASE=F32P08xG3 [PCIe boot mode]
@@ -39668,6 +39947,12 @@ pci:v00001171*
pci:v00001172*
ID_VENDOR_FROM_DATABASE=Altera Corporation
+pci:v00001172d000000A7*
+ ID_MODEL_FROM_DATABASE=Stratix V
+
+pci:v00001172d00000530*
+ ID_MODEL_FROM_DATABASE=Stratix IV
+
pci:v00001173*
ID_VENDOR_FROM_DATABASE=Adobe Systems, Inc
@@ -40088,6 +40373,9 @@ pci:v00001180d00000592sv00001028sd000001F3*
pci:v00001180d00000592sv00001028sd0000022F*
ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Inspiron 1525)
+pci:v00001180d00000592sv0000103Csd00001521*
+ ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (HP EliteBook 8540w)
+
pci:v00001180d00000592sv0000103Csd000030B5*
ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Presario V3242AU)
@@ -40241,6 +40529,9 @@ pci:v00001180d00000843sv00001028sd0000024F*
pci:v00001180d00000843sv0000103Csd000003B5*
ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Presario V3242AU)
+pci:v00001180d00000843sv0000103Csd00001521*
+ ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (HP EliteBook 8540w)
+
pci:v00001180d00000843sv0000103Csd000030B7*
ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Presario V6133CL)
@@ -42261,16 +42552,19 @@ pci:v000011F8d00008009*
ID_MODEL_FROM_DATABASE=PM8009 SPCve 8x6G
pci:v000011F8d00008032*
- ID_MODEL_FROM_DATABASE=ATTO Celerity FC8xEN
+ ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8
pci:v000011F8d00008032sv0000117Csd0000003A*
- ID_MODEL_FROM_DATABASE=ATTO Celerity FC8xEN (Celerity FC-81EN Fibre Channel Adapter)
+ ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 (Celerity FC-81EN Fibre Channel Adapter)
pci:v000011F8d00008032sv0000117Csd0000003B*
- ID_MODEL_FROM_DATABASE=ATTO Celerity FC8xEN (Celerity FC-82EN Fibre Channel Adapter)
+ ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 (Celerity FC-82EN Fibre Channel Adapter)
pci:v000011F8d00008032sv0000117Csd0000003C*
- ID_MODEL_FROM_DATABASE=ATTO Celerity FC8xEN (Celerity FC-84EN Fibre Channel Adapter)
+ ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 (Celerity FC-84EN Fibre Channel Adapter)
+
+pci:v000011F8d00008032sv0000117Csd0000403B*
+ ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 (ThunderLink FC 1082 Fibre Channel Adapter)
pci:v000011F8d00008053*
ID_MODEL_FROM_DATABASE=PM8053 SXP 12G 24-port SAS/SATA expander
@@ -42641,9 +42935,6 @@ pci:v00001210*
pci:v00001211*
ID_VENDOR_FROM_DATABASE=Braintech Inc
-pci:v00001212*
- ID_VENDOR_FROM_DATABASE=Kingston Technology Corp.
-
pci:v00001213*
ID_VENDOR_FROM_DATABASE=Applied Intelligent Systems, Inc.
@@ -43146,7 +43437,7 @@ pci:v00001233*
ID_VENDOR_FROM_DATABASE=Bus-Tech, Inc.
pci:v00001235*
- ID_VENDOR_FROM_DATABASE=Risq Modular Systems, Inc.
+ ID_VENDOR_FROM_DATABASE=SMART Modular Technologies
pci:v00001236*
ID_VENDOR_FROM_DATABASE=Sigma Designs Corporation
@@ -44525,6 +44816,9 @@ pci:v00001283d00008888*
pci:v00001283d00008889*
ID_MODEL_FROM_DATABASE=IT8889F PCI to ISA Bridge
+pci:v00001283d00008892*
+ ID_MODEL_FROM_DATABASE=IT8892E PCIe to PCI Bridge
+
pci:v00001283d00008893*
ID_MODEL_FROM_DATABASE=IT8893E PCIe to PCI Bridge
@@ -44685,7 +44979,7 @@ pci:v000012A3d00008105*
ID_MODEL_FROM_DATABASE=T8105 H100 Digital Switch
pci:v000012A4*
- ID_VENDOR_FROM_DATABASE=NTT Electronics Technology Company
+ ID_VENDOR_FROM_DATABASE=NTT Electronics Corporation
pci:v000012A5*
ID_VENDOR_FROM_DATABASE=Vision Dynamics Ltd.
@@ -46100,6 +46394,15 @@ pci:v00001344d00005180*
pci:v00001344d00005181*
ID_MODEL_FROM_DATABASE=9100 MAX NVMe SSD
+pci:v00001344d00005190*
+ ID_MODEL_FROM_DATABASE=9200 ECO NVMe SSD
+
+pci:v00001344d00005191*
+ ID_MODEL_FROM_DATABASE=9200 PRO NVMe SSD
+
+pci:v00001344d00005192*
+ ID_MODEL_FROM_DATABASE=9200 MAX NVMe SSD
+
pci:v00001345*
ID_VENDOR_FROM_DATABASE=Arescom Inc
@@ -48995,6 +49298,15 @@ pci:v00001425d00005017*
pci:v00001425d00005018*
ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Ethernet Controller
+pci:v00001425d00005019*
+ ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Ethernet Controller
+
+pci:v00001425d0000501A*
+ ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Ethernet Controller
+
+pci:v00001425d0000501B*
+ ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Ethernet Controller
+
pci:v00001425d00005080*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller
@@ -49112,6 +49424,9 @@ pci:v00001425d000050AB*
pci:v00001425d000050AC*
ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Ethernet Controller
+pci:v00001425d000050AD*
+ ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Ethernet Controller
+
pci:v00001425d00005401*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
@@ -49184,6 +49499,15 @@ pci:v00001425d00005417*
pci:v00001425d00005418*
ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Ethernet Controller
+pci:v00001425d00005419*
+ ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Ethernet Controller
+
+pci:v00001425d0000541A*
+ ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Ethernet Controller
+
+pci:v00001425d0000541B*
+ ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Ethernet Controller
+
pci:v00001425d00005480*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller
@@ -49301,6 +49625,9 @@ pci:v00001425d000054AB*
pci:v00001425d000054AC*
ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Ethernet Controller
+pci:v00001425d000054AD*
+ ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Ethernet Controller
+
pci:v00001425d00005501*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
@@ -49373,6 +49700,15 @@ pci:v00001425d00005517*
pci:v00001425d00005518*
ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Storage Controller
+pci:v00001425d00005519*
+ ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Storage Controller
+
+pci:v00001425d0000551A*
+ ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Storage Controller
+
+pci:v00001425d0000551B*
+ ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Storage Controller
+
pci:v00001425d00005580*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller
@@ -49490,6 +49826,9 @@ pci:v00001425d000055AB*
pci:v00001425d000055AC*
ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Storage Controller
+pci:v00001425d000055AD*
+ ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Storage Controller
+
pci:v00001425d00005601*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
@@ -49562,6 +49901,15 @@ pci:v00001425d00005617*
pci:v00001425d00005618*
ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Storage Controller
+pci:v00001425d00005619*
+ ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Storage Controller
+
+pci:v00001425d0000561A*
+ ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Storage Controller
+
+pci:v00001425d0000561B*
+ ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Storage Controller
+
pci:v00001425d00005680*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller
@@ -49679,6 +50027,9 @@ pci:v00001425d000056AB*
pci:v00001425d000056AC*
ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Storage Controller
+pci:v00001425d000056AD*
+ ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Storage Controller
+
pci:v00001425d00005701*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
@@ -49868,6 +50219,15 @@ pci:v00001425d00005817*
pci:v00001425d00005818*
ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Ethernet Controller [VF]
+pci:v00001425d00005819*
+ ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d0000581A*
+ ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d0000581B*
+ ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Ethernet Controller [VF]
+
pci:v00001425d00005880*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller [VF]
@@ -49985,6 +50345,9 @@ pci:v00001425d000058AB*
pci:v00001425d000058AC*
ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Ethernet Controller [VF]
+pci:v00001425d000058AD*
+ ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Ethernet Controller [VF]
+
pci:v00001425d00006001*
ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller
@@ -50048,6 +50411,12 @@ pci:v00001425d00006086*
pci:v00001425d00006087*
ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Ethernet Controller
+pci:v00001425d00006088*
+ ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Ethernet Controller
+
+pci:v00001425d00006089*
+ ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Ethernet Controller
+
pci:v00001425d00006401*
ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller
@@ -50111,6 +50480,12 @@ pci:v00001425d00006486*
pci:v00001425d00006487*
ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Ethernet Controller
+pci:v00001425d00006488*
+ ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Ethernet Controller
+
+pci:v00001425d00006489*
+ ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Ethernet Controller
+
pci:v00001425d00006501*
ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Storage Controller
@@ -50174,6 +50549,12 @@ pci:v00001425d00006586*
pci:v00001425d00006587*
ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Storage Controller
+pci:v00001425d00006588*
+ ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Storage Controller
+
+pci:v00001425d00006589*
+ ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Storage Controller
+
pci:v00001425d00006601*
ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Storage Controller
@@ -50237,6 +50618,12 @@ pci:v00001425d00006686*
pci:v00001425d00006687*
ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Storage Controller
+pci:v00001425d00006688*
+ ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Storage Controller
+
+pci:v00001425d00006689*
+ ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Storage Controller
+
pci:v00001425d00006801*
ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller [VF]
@@ -50300,6 +50687,12 @@ pci:v00001425d00006886*
pci:v00001425d00006887*
ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Ethernet Controller [VF]
+pci:v00001425d00006888*
+ ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d00006889*
+ ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Ethernet Controller [VF]
+
pci:v00001425d0000A000*
ID_MODEL_FROM_DATABASE=PE10K Unified Wire Ethernet Controller
@@ -50510,6 +50903,9 @@ pci:v0000144Dd0000A802*
pci:v0000144Dd0000A804*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM961/PM961
+pci:v0000144Dd0000A808*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM981/PM981
+
pci:v0000144Dd0000A820*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X
@@ -50559,37 +50955,61 @@ pci:v0000144Dd0000A821sv00001028sd00001FC4*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 1.6TB AIC)
pci:v0000144Dd0000A822*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb
pci:v0000144Dd0000A822sv00001014sd00000621*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (PCIe3 1.6TB NVMe Flash Adapter II x8)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 1.6TB NVMe Flash Adapter II x8)
pci:v0000144Dd0000A822sv00001014sd00000622*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (PCIe3 3.2TB NVMe Flash Adapter II x8)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 3.2TB NVMe Flash Adapter II x8)
pci:v0000144Dd0000A822sv00001014sd00000629*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (PCIe3 6.4TB NVMe Flash Adapter II x8)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 6.4TB NVMe Flash Adapter II x8)
pci:v0000144Dd0000A822sv00001028sd00001FD9*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 800GB SFF)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 800GB SFF)
pci:v0000144Dd0000A822sv00001028sd00001FDA*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 1.6TB SFF)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 1.6TB SFF)
pci:v0000144Dd0000A822sv00001028sd00001FDB*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 3.2TB SFF)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 3.2TB SFF)
pci:v0000144Dd0000A822sv00001028sd00001FDC*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 6.4TB SFF)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 6.4TB SFF)
pci:v0000144Dd0000A822sv00001028sd00001FDD*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 1.6TB AIC)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 1.6TB AIC)
pci:v0000144Dd0000A822sv00001028sd00001FDE*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 3.2TB AIC)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 3.2TB AIC)
pci:v0000144Dd0000A822sv00001028sd00001FDF*
- ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 6.4TB AIC)
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 6.4TB AIC)
+
+pci:v0000144Dd0000A822sv00001028sd00001FF3*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 1.6TB SFF)
+
+pci:v0000144Dd0000A822sv00001028sd00001FF4*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 3.2TB SFF)
+
+pci:v0000144Dd0000A822sv00001028sd00001FF5*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 6.4TB SFF)
+
+pci:v0000144Dd0000A822sv00001028sd00001FF6*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 12.8TB SFF)
+
+pci:v0000144Dd0000A822sv00001028sd00001FF7*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 1.6TB AIC)
+
+pci:v0000144Dd0000A822sv00001028sd00001FF8*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 3.2TB AIC)
+
+pci:v0000144Dd0000A822sv00001028sd00001FF9*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 6.4TB AIC)
+
+pci:v0000144Dd0000A822sv00001028sd00001FFA*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 12.8TB AIC)
pci:v0000144E*
ID_VENDOR_FROM_DATABASE=OLITEC
@@ -52052,6 +52472,9 @@ pci:v000014E4d00001681*
pci:v000014E4d00001682*
ID_MODEL_FROM_DATABASE=NetXtreme BCM57762 Gigabit Ethernet PCIe
+pci:v000014E4d00001682sv0000106Bsd000000F6*
+ ID_MODEL_FROM_DATABASE=NetXtreme BCM57762 Gigabit Ethernet PCIe (Thunderbolt to Gigabit Ethernet Adapter)
+
pci:v000014E4d00001683*
ID_MODEL_FROM_DATABASE=NetXtreme BCM57767 Gigabit Ethernet PCIe
@@ -52566,10 +52989,13 @@ pci:v000014E4d000016D7*
ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller
pci:v000014E4d000016D7sv000014E4sd00001202*
- ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957412M4122 OCP 1x25G Type1 wRoCE)
+ ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957412M4122C OCP 1x25G Type1 wRoCE)
+
+pci:v000014E4d000016D7sv000014E4sd00001402*
+ ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957414A4142CC 10Gb/25Gb Ethernet PCIe)
pci:v000014E4d000016D7sv000014E4sd00001404*
- ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957414M4142 OCP 2x25G Type1 wRoCE)
+ ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957414M4142C OCP 2x25G Type1 wRoCE)
pci:v000014E4d000016D7sv00001590sd0000020E*
ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Ethernet 25Gb 2-port 631SFP28 Adapter)
@@ -55461,7 +55887,7 @@ pci:v000015B3d0000024E*
ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2, Flash recovery mode]
pci:v000015B3d0000024F*
- ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2, Flash recovery mode]
+ ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2, Secure Flash recovery mode]
pci:v000015B3d00000262*
ID_MODEL_FROM_DATABASE=MT27710 [ConnectX-4 Lx Programmable] EN
@@ -55511,6 +55937,9 @@ pci:v000015B3d00001003sv000015B3sd00000028*
pci:v000015B3d00001003sv000015B3sd00000059*
ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Mezzanine Card)
+pci:v000015B3d00001003sv000015B3sd00000064*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 EN 10/40 GbE Single Port QSFP+ Adapter (MCX313A-BCBT))
+
pci:v000015B3d00001003sv000015B3sd00000065*
ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Dual Port QSFP+ Adapter)
@@ -55650,7 +56079,7 @@ pci:v000015B3d00001015sv000015B3sd00000001*
ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx EN network interface card, 25GbE single-port SFP28, PCIe3.0 x8, tall bracket, ROHS R6)
pci:v000015B3d00001015sv000015B3sd00000003*
- ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx EN network interface card, 25GbE dual-port SFP28, PCIe3.0 x8, tall bracket, ROHS R6)
+ ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (Stand-up ConnectX-4 Lx EN, 25GbE dual-port SFP28, PCIe3.0 x8, MCX4121A-ACAT)
pci:v000015B3d00001015sv000015B3sd00000004*
ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx Stand-up dual-port 10GbE MCX4121A-XCAT)
@@ -55658,9 +56087,6 @@ pci:v000015B3d00001015sv000015B3sd00000004*
pci:v000015B3d00001015sv000015B3sd00000005*
ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (Mellanox Technologies ConnectX-4 Lx Stand-up single-port 40GbE MCX4131A-BCAT)
-pci:v000015B3d00001015sv000015B3sd00000016*
- ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx 25 GbE Dual Port SFP28 Adapter)
-
pci:v000015B3d00001015sv000015B3sd00000020*
ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (MCX4411A-ACQN, ConnectX-4 Lx EN OCP, 1x25Gb)
@@ -55746,34 +56172,37 @@ pci:v000015B3d00006282*
ID_MODEL_FROM_DATABASE=MT25208 [InfiniHost III Ex]
pci:v000015B3d00006340*
- ID_MODEL_FROM_DATABASE=MT25408 [ConnectX VPI - IB SDR / 10GigE]
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-SI ConnectX, Dual Port 10Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface
pci:v000015B3d0000634A*
- ID_MODEL_FROM_DATABASE=MT25418 [ConnectX VPI PCIe 2.0 2.5GT/s - IB DDR / 10GigE]
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-DI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface
+
+pci:v000015B3d0000634Asv00001014sd00001014*
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-DI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface (4X InfiniBand DDR Expansion Card (CFFh) for IBM BladeCenter)
pci:v000015B3d00006368*
ID_MODEL_FROM_DATABASE=MT25448 [ConnectX EN 10GigE, PCIe 2.0 2.5GT/s]
pci:v000015B3d00006372*
- ID_MODEL_FROM_DATABASE=MT25408 [ConnectX EN 10GigE 10GBaseT, PCIe 2.0 2.5GT/s]
+ ID_MODEL_FROM_DATABASE=MT25458 ConnectX EN 10GBASE-T PCIe 2.5 GT/s
pci:v000015B3d00006732*
- ID_MODEL_FROM_DATABASE=MT26418 [ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE]
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-GI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface
pci:v000015B3d0000673C*
- ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE]
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface
pci:v000015B3d0000673Csv00001014sd00000415*
- ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] (PCIe2 2-port 4X InfiniBand QDR Adapter for Power)
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface (PCIe2 2-port 4X InfiniBand QDR Adapter for Power)
pci:v000015B3d0000673Csv00001014sd00000487*
- ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] (GX++ 1-port 4X IB QDR Adapter for Power 795)
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface (GX++ 1-port 4X IB QDR Adapter for Power 795)
pci:v000015B3d0000673Csv0000103Csd00001782*
- ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] (4X QDR InfiniBand Mezzanine HCA for c-Class BladeSystem)
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface (4X QDR InfiniBand Mezzanine HCA for c-Class BladeSystem)
pci:v000015B3d0000673Csv000015B3sd00000021*
- ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] (HP InfiniBand 4X QDR CX-2 PCI-e G2 Dual Port HCA)
+ ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface (HP InfiniBand 4X QDR CX-2 PCI-e G2 Dual Port HCA)
pci:v000015B3d00006746*
ID_MODEL_FROM_DATABASE=MT26438 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virtualization+]
@@ -55787,8 +56216,11 @@ pci:v000015B3d00006746sv0000103Csd00003349*
pci:v000015B3d00006750*
ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s]
+pci:v000015B3d00006750sv00001014sd00000416*
+ ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (PCIe2 2-Port 10GbE RoCE SFP+ Adapter)
+
pci:v000015B3d00006750sv00001014sd00000461*
- ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (2-Port 10 GbE RoCE SR LP PCIe2 (rev b0))
+ ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (PCIe2 2-Port 10GbE RoCE SR Adapter)
pci:v000015B3d00006750sv000015B3sd00000018*
ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (HP 10 GbE PCI-e G2 Dual-Port NIC (rev C1))
@@ -55797,7 +56229,7 @@ pci:v000015B3d00006750sv000015B3sd00006572*
ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (IBM Flex System EN4132 2-port 10Gb RoCE Adapter)
pci:v000015B3d0000675A*
- ID_MODEL_FROM_DATABASE=MT25408 [ConnectX EN 10GigE 10GBaseT, PCIe Gen2 5GT/s]
+ ID_MODEL_FROM_DATABASE=MT26458 ConnectX EN 10GBASE-T PCIe Gen2 5.0 GT/s
pci:v000015B3d00006764*
ID_MODEL_FROM_DATABASE=MT26468 [ConnectX EN 10GigE, PCIe 2.0 5GT/s Virtualization+]
@@ -56445,7 +56877,7 @@ pci:v00001642*
ID_VENDOR_FROM_DATABASE=Bitland(ShenZhen) Information Technology Co., Ltd.
pci:v00001657*
- ID_VENDOR_FROM_DATABASE=Brocade Communications Systems, Inc.
+ ID_VENDOR_FROM_DATABASE=Cavium QLogic
pci:v00001657d00000013*
ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA
@@ -56484,16 +56916,16 @@ pci:v00001657d00000021*
ID_MODEL_FROM_DATABASE=804 8Gbps FC HBA for HP Bladesystem c-class
pci:v00001657d00000022*
- ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter
+ ID_MODEL_FROM_DATABASE=BR-1860 Fabric Adapter
pci:v00001657d00000022sv00001657sd00000022*
- ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter (10Gbps CNA - FCOE)
+ ID_MODEL_FROM_DATABASE=BR-1860 Fabric Adapter (10Gbps CNA - FCOE)
pci:v00001657d00000022sv00001657sd00000023*
- ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter (10Gbps CNA - LL)
+ ID_MODEL_FROM_DATABASE=BR-1860 Fabric Adapter (10Gbps CNA - LL)
pci:v00001657d00000022sv00001657sd00000024*
- ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter (16Gbps FC HBA)
+ ID_MODEL_FROM_DATABASE=BR-1860 Fabric Adapter (16Gbps FC HBA)
pci:v00001657d00000023*
ID_MODEL_FROM_DATABASE=1867/1869 16Gbps FC HBA
@@ -57500,6 +57932,9 @@ pci:v0000168Cd00000041*
pci:v0000168Cd00000042*
ID_MODEL_FROM_DATABASE=QCA9377 802.11ac Wireless Network Adapter
+pci:v0000168Cd00000046*
+ ID_MODEL_FROM_DATABASE=QCA9984 802.11ac Wave 2 Wireless Network Adapter
+
pci:v0000168Cd00000050*
ID_MODEL_FROM_DATABASE=QCA9887 802.11ac Wireless Network Adapter
@@ -57593,6 +58028,9 @@ pci:v000016BE*
pci:v000016C3*
ID_VENDOR_FROM_DATABASE=Synopsys, Inc.
+pci:v000016C3d0000EDDA*
+ ID_MODEL_FROM_DATABASE=EPMockUp
+
pci:v000016C6*
ID_VENDOR_FROM_DATABASE=Micrel-Kendin
@@ -58952,6 +59390,9 @@ pci:v000017DFd00001915*
pci:v000017DFd00001916*
ID_MODEL_FROM_DATABASE=VirtexUS PCIe Accelerator Board [DNVUF2_HPC_PCIe]
+pci:v000017DFd00001917*
+ ID_MODEL_FROM_DATABASE=UltrascalePlus PCIe Accelerator Board [DNPCIe_400G_VU_LL]
+
pci:v000017DFd00001A00*
ID_MODEL_FROM_DATABASE=Virtex6 PCIe DMA Netlist Design
@@ -58982,6 +59423,12 @@ pci:v000017DFd00001A09*
pci:v000017DFd00001A0A*
ID_MODEL_FROM_DATABASE=VirtexUS PCIe Darklite Design [DNVUF2_HPC_PCIe]
+pci:v000017DFd00001A0B*
+ ID_MODEL_FROM_DATABASE=UltrascalePlus PCIe Darklite Design [DNPCIe_400G_VU_LL]
+
+pci:v000017DFd00001A0C*
+ ID_MODEL_FROM_DATABASE=KintexUS PCIe DRAM Packet Capture Design [DNPCIe_40G_KU_LL]
+
pci:v000017E4*
ID_VENDOR_FROM_DATABASE=Sectra AB
@@ -60389,6 +60836,9 @@ pci:v00001924d00000B03sv00001924sd0000801D*
pci:v00001924d00000B03sv00001924sd0000801E*
ID_MODEL_FROM_DATABASE=SFC9250 10/25/40/50/100G Ethernet Controller (x2542-R1 2000 Series 40/100G Adapter)
+pci:v00001924d00000B03sv00001924sd00008022*
+ ID_MODEL_FROM_DATABASE=SFC9250 10/25/40/50/100G Ethernet Controller (x2522-R2 2000 Series 10/25G Adapter)
+
pci:v00001924d00001803*
ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (Virtual Function)
@@ -61274,9 +61724,138 @@ pci:v000019E3d0000DD52*
pci:v000019E5*
ID_VENDOR_FROM_DATABASE=Huawei Technologies Co., Ltd.
+pci:v000019E5d00000123*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD
+
+pci:v000019E5d00000123sv000019E5sd00003022*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 800GB 2.5" U.2)
+
+pci:v000019E5d00000123sv000019E5sd00003023*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 1200GB 2.5" U.2)
+
+pci:v000019E5d00000123sv000019E5sd00003024*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 1600GB 2.5" U.2)
+
+pci:v000019E5d00000123sv000019E5sd00003025*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 2000GB 2.5" U.2)
+
+pci:v000019E5d00000123sv000019E5sd00003026*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 3200GB 2.5" U.2)
+
+pci:v000019E5d00000123sv000019E5sd00003033*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600C V3 1200GB HHHL AIC)
+
+pci:v000019E5d00000123sv000019E5sd00003034*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600C V3 1600GB HHHL AIC)
+
+pci:v000019E5d00000123sv000019E5sd00003036*
+ ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600C V3 3200GB HHHL AIC)
+
+pci:v000019E5d00000200*
+ ID_MODEL_FROM_DATABASE=Hi1822 Family (2*25GE)
+
+pci:v000019E5d00000201*
+ ID_MODEL_FROM_DATABASE=Hi1822 Family (2*100GE)
+
+pci:v000019E5d00001710*
+ ID_MODEL_FROM_DATABASE=iBMA Virtual Network Adapter
+
pci:v000019E5d00001711*
ID_MODEL_FROM_DATABASE=Hi1710 [iBMC Intelligent Management system chip w/VGA support]
+pci:v000019E5d00001822*
+ ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE)
+
+pci:v000019E5d0000371E*
+ ID_MODEL_FROM_DATABASE=Hi1822 Family Virtual Bridge
+
+pci:v000019E5d0000A120*
+ ID_MODEL_FROM_DATABASE=HiSilicon PCIe Root Port with Gen4
+
+pci:v000019E5d0000A121*
+ ID_MODEL_FROM_DATABASE=HiSilicon PCI-PCI Bridge
+
+pci:v000019E5d0000A122*
+ ID_MODEL_FROM_DATABASE=HiSilicon Embedded DMA Engine
+
+pci:v000019E5d0000A124*
+ ID_MODEL_FROM_DATABASE=HiSilicon Internal SDI Function Engine
+
+pci:v000019E5d0000A125*
+ ID_MODEL_FROM_DATABASE=HiSilicon SDI Network Controller
+
+pci:v000019E5d0000A126*
+ ID_MODEL_FROM_DATABASE=HiSilicon SDI NVMe Storage Controller
+
+pci:v000019E5d0000A127*
+ ID_MODEL_FROM_DATABASE=HiSilicon SDI Accelerator
+
+pci:v000019E5d0000A12A*
+ ID_MODEL_FROM_DATABASE=HiSilicon Add-on PCI-PCI Bridge
+
+pci:v000019E5d0000A220*
+ ID_MODEL_FROM_DATABASE=HNS GE Network Controller
+
+pci:v000019E5d0000A221*
+ ID_MODEL_FROM_DATABASE=HNS GE/10GE/25GE Network Controller
+
+pci:v000019E5d0000A222*
+ ID_MODEL_FROM_DATABASE=HNS GE/10GE/25GE RDMA Network Controller
+
+pci:v000019E5d0000A224*
+ ID_MODEL_FROM_DATABASE=HNS GE/10GE/25GE/50GE RDMA Network Controller
+
+pci:v000019E5d0000A226*
+ ID_MODEL_FROM_DATABASE=HNS GE/10GE/25GE/50GE/100GE RDMA Network Controller
+
+pci:v000019E5d0000A22A*
+ ID_MODEL_FROM_DATABASE=HiSilicon Network For SDI
+
+pci:v000019E5d0000A22E*
+ ID_MODEL_FROM_DATABASE=HNS Network Controller (Virtual Function)
+
+pci:v000019E5d0000A22F*
+ ID_MODEL_FROM_DATABASE=HNS RDMA Network Controller (Virtual Function)
+
+pci:v000019E5d0000A230*
+ ID_MODEL_FROM_DATABASE=HiSilicon SAS 3.0 HBA
+
+pci:v000019E5d0000A235*
+ ID_MODEL_FROM_DATABASE=HiSilicon AHCI HBA
+
+pci:v000019E5d0000A238*
+ ID_MODEL_FROM_DATABASE=HiSilicon USB 3.0 Host Controller
+
+pci:v000019E5d0000A239*
+ ID_MODEL_FROM_DATABASE=HiSilicon USB 2.0 2-port Host Controller
+
+pci:v000019E5d0000A23A*
+ ID_MODEL_FROM_DATABASE=HiSilicon USB 2.0 Host Controller
+
+pci:v000019E5d0000A250*
+ ID_MODEL_FROM_DATABASE=HiSilicon ZIP Engine
+
+pci:v000019E5d0000A251*
+ ID_MODEL_FROM_DATABASE=HiSilicon ZIP Engine(Virtual Function)
+
+pci:v000019E5d0000A255*
+ ID_MODEL_FROM_DATABASE=HiSilicon SEC Engine
+
+pci:v000019E5d0000A256*
+ ID_MODEL_FROM_DATABASE=HiSilicon SEC Engine(Virtual Function)
+
+pci:v000019E5d0000A258*
+ ID_MODEL_FROM_DATABASE=HiSilicon HPRE Engine
+
+pci:v000019E5d0000A259*
+ ID_MODEL_FROM_DATABASE=HiSilicon HPRE Engine(Virtual Function)
+
+pci:v000019E5d0000A25A*
+ ID_MODEL_FROM_DATABASE=HiSilicon RDE Engine
+
+pci:v000019E5d0000A25B*
+ ID_MODEL_FROM_DATABASE=HiSilicon RDE Engine(Virtual Function)
+
pci:v000019E7*
ID_VENDOR_FROM_DATABASE=NET (Network Equipment Technologies)
@@ -61428,7 +62007,7 @@ pci:v00001A41d00002000*
ID_MODEL_FROM_DATABASE=TILE-Gx PCI Express Root Port
pci:v00001A4A*
- ID_VENDOR_FROM_DATABASE=SLAC National Accelerator Lab PPA-REG
+ ID_VENDOR_FROM_DATABASE=SLAC National Accelerator Lab TID-AIR
pci:v00001A4Ad00001000*
ID_MODEL_FROM_DATABASE=MCOR Power Supply Controller
@@ -61436,6 +62015,9 @@ pci:v00001A4Ad00001000*
pci:v00001A4Ad00001010*
ID_MODEL_FROM_DATABASE=AMC EVR - Stockholm Timing Board
+pci:v00001A4Ad00001020*
+ ID_MODEL_FROM_DATABASE=Cluster On Board (COB) Ethernet Switch
+
pci:v00001A4Ad00002000*
ID_MODEL_FROM_DATABASE=PGPCard - 4 Lane
@@ -61448,6 +62030,9 @@ pci:v00001A4Ad00002010*
pci:v00001A4Ad00002020*
ID_MODEL_FROM_DATABASE=PGP-GEN3 PCIe
+pci:v00001A4Ad00002030*
+ ID_MODEL_FROM_DATABASE=AXI Stream DAQ PCIe card
+
pci:v00001A51*
ID_VENDOR_FROM_DATABASE=Hectronic AB
@@ -61889,6 +62474,9 @@ pci:v00001B21d00001142*
pci:v00001B21d00001242*
ID_MODEL_FROM_DATABASE=ASM1142 USB 3.1 Host Controller
+pci:v00001B21d00001343*
+ ID_MODEL_FROM_DATABASE=ASM1143 USB 3.1 Host Controller
+
pci:v00001B2C*
ID_VENDOR_FROM_DATABASE=Opal-RT Technologies Inc.
@@ -62136,10 +62724,10 @@ pci:v00001B55d0000F1C4*
ID_MODEL_FROM_DATABASE=Dual ASI-RX/TX-CI card
pci:v00001B66*
- ID_VENDOR_FROM_DATABASE=Deltacast
+ ID_VENDOR_FROM_DATABASE=DELTACAST
pci:v00001B66d00000007*
- ID_MODEL_FROM_DATABASE=Delta-3G-elp-11 SDI I/O Board
+ ID_MODEL_FROM_DATABASE=DELTA-3G-elp-d
pci:v00001B6F*
ID_VENDOR_FROM_DATABASE=Etron Technology, Inc.
@@ -62462,6 +63050,15 @@ pci:v00001C32*
pci:v00001C33*
ID_VENDOR_FROM_DATABASE=Daktronics, Inc
+pci:v00001C36*
+ ID_VENDOR_FROM_DATABASE=Annapurna Labs Ltd.
+
+pci:v00001C36d00000001*
+ ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter
+
+pci:v00001C36d00000002*
+ ID_MODEL_FROM_DATABASE=SFP+ 10G Ethernet Adapter
+
pci:v00001C3B*
ID_VENDOR_FROM_DATABASE=Accensus, LLC
@@ -62528,6 +63125,9 @@ pci:v00001C8A*
pci:v00001C8Ad00000001*
ID_MODEL_FROM_DATABASE=Hunter PCI Express
+pci:v00001C8C*
+ ID_VENDOR_FROM_DATABASE=Mobiveil, Inc.
+
pci:v00001CB1*
ID_VENDOR_FROM_DATABASE=Collion UG & Co.KG
@@ -62858,6 +63458,9 @@ pci:v00001D65d000004DE*
pci:v00001D6A*
ID_VENDOR_FROM_DATABASE=Aquantia Corp.
+pci:v00001D6Ad00000001*
+ ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
+
pci:v00001D6Ad000007B1*
ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
@@ -62876,6 +63479,9 @@ pci:v00001D6Ad000087B1*
pci:v00001D6Ad0000D107*
ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
+pci:v00001D6Ad0000D107sv00001043sd00008741*
+ ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] (XG-C100C)
+
pci:v00001D6Ad0000D108*
ID_MODEL_FROM_DATABASE=AQC108 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
@@ -62933,6 +63539,9 @@ pci:v00001D6Cd0000100Esv00001D6Csd00002001*
pci:v00001D6Cd00004200*
ID_MODEL_FROM_DATABASE=A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument]
+pci:v00001D72*
+ ID_VENDOR_FROM_DATABASE=Xiaomi
+
pci:v00001D78*
ID_VENDOR_FROM_DATABASE=DERA
@@ -63044,6 +63653,9 @@ pci:v00001DA1*
pci:v00001DA2*
ID_VENDOR_FROM_DATABASE=Sapphire Technology Limited
+pci:v00001DBB*
+ ID_VENDOR_FROM_DATABASE=NGD Systems, Inc.
+
pci:v00001DE1*
ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd.
@@ -63107,6 +63719,12 @@ pci:v00001DF7d00000002*
pci:v00001DF7d00000003*
ID_MODEL_FROM_DATABASE=alst4x
+pci:v00001DFC*
+ ID_VENDOR_FROM_DATABASE=JSC NT-COM
+
+pci:v00001DFCd00001181*
+ ID_MODEL_FROM_DATABASE=TDM 8 Port E1/T1/J1 Adapter
+
pci:v00001FC0*
ID_VENDOR_FROM_DATABASE=Ascom (Finland) Oy
@@ -63252,7 +63870,7 @@ pci:v00001FC9d00004027sv00001432sd00008104*
ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (10 Gigabit Ethernet PCI Express Adapter)
pci:v00001FC9d00004027sv00001546sd00004027*
- ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (IOI9710P 10Gbase-T/NBASE-T Ethernet Adapter)
+ ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (GE10-PCIE4XG202P 10Gbase-T/NBASE-T Ethernet Adapter)
pci:v00001FC9d00004027sv00001FC9sd00003015*
ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (Ethernet Adapter)
@@ -63311,6 +63929,9 @@ pci:v00002116*
pci:v000021C3*
ID_VENDOR_FROM_DATABASE=21st Century Computer Corp.
+pci:v000022DB*
+ ID_VENDOR_FROM_DATABASE=Missing Link Electronics, Inc.
+
pci:v00002304*
ID_VENDOR_FROM_DATABASE=Colorgraphic Communications Corp.
@@ -63321,7 +63942,7 @@ pci:v00002348d00002010*
ID_MODEL_FROM_DATABASE=8142 100VG/AnyLAN
pci:v00002646*
- ID_VENDOR_FROM_DATABASE=Kingston Technologies
+ ID_VENDOR_FROM_DATABASE=Kingston Technology Company, Inc.
pci:v0000270B*
ID_VENDOR_FROM_DATABASE=Xantel Corporation
@@ -66786,19 +67407,19 @@ pci:v00008086d00000A53*
ID_MODEL_FROM_DATABASE=DC P3520 SSD
pci:v00008086d00000A54*
- ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500
+ ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500/P4600
pci:v00008086d00000A54sv00001028sd00001FE1*
- ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500 (Express Flash NVMe 1TB 2.5" U.2 (P4500))
+ ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500/P4600 (Express Flash NVMe 1TB 2.5" U.2 (P4500))
pci:v00008086d00000A54sv00001028sd00001FE2*
- ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500 (Express Flash NVMe 2TB 2.5" U.2 (P4500))
+ ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500/P4600 (Express Flash NVMe 2TB 2.5" U.2 (P4500))
pci:v00008086d00000A54sv00001028sd00001FE3*
- ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500 (Express Flash NVMe 4TB 2.5" U.2 (P4500))
+ ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500/P4600 (Express Flash NVMe 4TB 2.5" U.2 (P4500))
pci:v00008086d00000A54sv00001028sd00001FE4*
- ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500 (Express Flash NVMe 4TB HHHL AIC (P4500))
+ ID_MODEL_FROM_DATABASE=Express Flash NVMe P4500/P4600 (Express Flash NVMe 4TB HHHL AIC (P4500))
pci:v00008086d00000A55*
ID_MODEL_FROM_DATABASE=Express Flash NVMe P4600
@@ -68163,40 +68784,40 @@ pci:v00008086d0000105B*
ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper)
pci:v00008086d0000105E*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications)
pci:v00008086d0000105Esv0000103Csd00007044*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (NC360T PCI Express Dual Port Gigabit Server Adapter)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (NC360T PCI Express Dual Port Gigabit Server Adapter)
pci:v00008086d0000105Esv0000103Csd0000704E*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Dual Port 1000Base-T (PCIe) [AD337A])
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (Dual Port 1000Base-T (PCIe) [AD337A])
pci:v00008086d0000105Esv00001775sd00001100*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (CR11/VR11 Single Board Computer)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (CR11/VR11 Single Board Computer)
pci:v00008086d0000105Esv00001775sd00006003*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Telum GE-QT)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (Telum GE-QT)
pci:v00008086d0000105Esv000018DFsd00001214*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (2x 1GbE, PCIe x1, dual Intel 82571EB chips)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (2x 1GbE, PCIe x1, dual Intel 82571EB chips)
pci:v00008086d0000105Esv00008086sd0000005E*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Server Connection)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Server Connection)
pci:v00008086d0000105Esv00008086sd0000105E*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Network Connection)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Network Connection)
pci:v00008086d0000105Esv00008086sd000010D5*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (82571PT Gigabit PT Quad Port Server ExpressModule)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (82571PT Gigabit PT Quad Port Server ExpressModule)
pci:v00008086d0000105Esv00008086sd0000115E*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Server Adapter)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Server Adapter)
pci:v00008086d0000105Esv00008086sd0000125E*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Server Adapter)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Server Adapter)
pci:v00008086d0000105Esv00008086sd0000135E*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Dual Port Server Adapter)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Server Adapter)
pci:v00008086d0000105F*
ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller
@@ -68613,22 +69234,22 @@ pci:v00008086d000010BB*
ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Serdes)
pci:v00008086d000010BC*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper)
pci:v00008086d000010BCsv00001014sd00000368*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (4-Port 10/100/1000 Base-TX PCI Express Adapter for POWER)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (4-Port 10/100/1000 Base-TX PCI Express Adapter for POWER)
pci:v00008086d000010BCsv0000103Csd0000704B*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (NC364T PCI Express Quad Port Gigabit Server Adapter)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (NC364T PCI Express Quad Port Gigabit Server Adapter)
pci:v00008086d000010BCsv0000108Esd000011BC*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (x4 PCI-Express Quad Gigabit Ethernet UTP Low Profile Adapter)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (Quad Port Adapter)
pci:v00008086d000010BCsv00008086sd000010BC*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (PRO/1000 PT Quad Port LP Server Adapter)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (PRO/1000 PT Quad Port LP Server Adapter)
pci:v00008086d000010BCsv00008086sd000011BC*
- ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (PRO/1000 PT Quad Port LP Server Adapter)
+ ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (PRO/1000 PT Quad Port LP Server Adapter (Kirkwood Low Profile))
pci:v00008086d000010BD*
ID_MODEL_FROM_DATABASE=82566DM-2 Gigabit Network Connection
@@ -70307,6 +70928,9 @@ pci:v00008086d00001563sv00001028sd00001FA8*
pci:v00008086d00001563sv00001028sd00001FA9*
ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10G 4P X550 rNDC)
+pci:v00008086d00001563sv00001170sd00000001*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Intel Ethernet Controller X550-T2 OCP card)
+
pci:v00008086d00001563sv000014C0sd00001201*
ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (X550 10Gb 2P RJ45 OCP Mezz)
@@ -70316,6 +70940,9 @@ pci:v00008086d00001563sv00001590sd000000D1*
pci:v00008086d00001563sv00001590sd000000D2*
ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10Gb 2-port 562FLR-T Adapter)
+pci:v00008086d00001563sv000016B8sd00007217*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Twin10G Thunderbolt 3 Edition)
+
pci:v00008086d00001563sv000018D4sd00000C08*
ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (X550 10Gb 2-port RJ45 OCP Mezz Card MOP81-I-10GT2)
@@ -70730,6 +71357,9 @@ pci:v00008086d000015AB*
pci:v00008086d000015AC*
ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE SFP+
+pci:v00008086d000015ACsv00001059sd00000160*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE SFP+ (RD-01167 10GbE interface)
+
pci:v00008086d000015AD*
ID_MODEL_FROM_DATABASE=Ethernet Connection X552/X557-AT 10GBASE-T
@@ -71211,76 +71841,82 @@ pci:v00008086d00001962sv0000105Asd00000000*
ID_MODEL_FROM_DATABASE=80960RM (i960RM) Microprocessor (SuperTrak SX6000 I2O CPU)
pci:v00008086d000019AC*
- ID_MODEL_FROM_DATABASE=DNV SMBus Contoller - Host
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SMBus Contoller - Host
pci:v00008086d000019B0*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019B1*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019B2*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019B3*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019B4*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019B5*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019B6*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019B7*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019BE*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019BF*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 0
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0
pci:v00008086d000019C0*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019C1*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019C2*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019C3*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019C4*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019C5*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019C6*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019C7*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019CE*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
pci:v00008086d000019CF*
- ID_MODEL_FROM_DATABASE=DNV SATA Controller 1
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1
+
+pci:v00008086d000019D0*
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series USB 3.0 xHCI Controller
pci:v00008086d000019DC*
- ID_MODEL_FROM_DATABASE=DNV LPC or eSPI
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series LPC or eSPI
pci:v00008086d000019DF*
- ID_MODEL_FROM_DATABASE=DNV SMBus controller
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SMBus controller
pci:v00008086d000019E0*
- ID_MODEL_FROM_DATABASE=DNV SPI Controller
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SPI Controller
+
+pci:v00008086d000019E2*
+ ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series QuickAssist Technology
pci:v00008086d00001A21*
ID_MODEL_FROM_DATABASE=82840 840 [Carmel] Chipset Host Bridge (Hub A)
@@ -71918,6 +72554,9 @@ pci:v00008086d00001D6A*
pci:v00008086d00001D6B*
ID_MODEL_FROM_DATABASE=C602 chipset 4-Port SATA Storage Control Unit
+pci:v00008086d00001D6Bsv00000497sd00001028*
+ ID_MODEL_FROM_DATABASE=C602 chipset 4-Port SATA Storage Control Unit (Dell Precision T3600)
+
pci:v00008086d00001D6C*
ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit
@@ -81353,6 +81992,9 @@ pci:v00008086d0000372C*
pci:v00008086d0000373F*
ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 IOxAPIC
+pci:v00008086d000037C8*
+ ID_MODEL_FROM_DATABASE=C62x Chipset QuickAssist Technology
+
pci:v00008086d000037CD*
ID_MODEL_FROM_DATABASE=Ethernet Virtual Function 700 Series
@@ -81419,6 +82061,9 @@ pci:v00008086d000037D1sv000017AAsd00004022*
pci:v00008086d000037D2*
ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T
+pci:v00008086d000037D2sv00001170sd000037D2*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T
+
pci:v00008086d000037D2sv000014CDsd00000030*
ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Ethernet OCP 2x10G RJ45 Phy Card [USI-X557-10GbaseT])
@@ -82532,6 +83177,39 @@ pci:v00008086d00003CF5*
pci:v00008086d00003CF6*
ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 System Address Decoder
+pci:v00008086d00003E18*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00003E1F*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00003E81*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor PCIe Controller (x16)
+
+pci:v00008086d00003E85*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor PCIe Controller (x8)
+
+pci:v00008086d00003E89*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor PCIe Controller (x4)
+
+pci:v00008086d00003E91*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor Gaussian Mixture Model
+
+pci:v00008086d00003EC2*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00003EC4*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00003EC6*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00003ECA*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00003ED0*
+ ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers
+
pci:v00008086d00004000*
ID_MODEL_FROM_DATABASE=5400 Chipset Memory Controller Hub
@@ -83450,6 +84128,9 @@ pci:v00008086d00006F52*
pci:v00008086d00006F53*
ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 3
+pci:v00008086d00006F54*
+ ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickAssist Technology
+
pci:v00008086d00006F60*
ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1
@@ -85268,6 +85949,9 @@ pci:v00008086d00009D48*
pci:v00008086d00009D48sv00001028sd000006F3*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (Latitude 3570)
+pci:v00008086d00009D4E*
+ ID_MODEL_FROM_DATABASE=Intel(R) 100 Series Chipset Family LPC Controller/eSPI Controller - 9D4E
+
pci:v00008086d00009D56*
ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller
@@ -85934,6 +86618,48 @@ pci:v00008086d0000A2EE*
pci:v00008086d0000A2F0*
ID_MODEL_FROM_DATABASE=200 Series PCH HD Audio
+pci:v00008086d0000A304*
+ ID_MODEL_FROM_DATABASE=H370 Chipset LPC/eSPI Controller
+
+pci:v00008086d0000A323*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH SMBus Controller
+
+pci:v00008086d0000A324*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH SPI Controller
+
+pci:v00008086d0000A32C*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port 21
+
+pci:v00008086d0000A330*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port 9
+
+pci:v00008086d0000A342*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port 19
+
+pci:v00008086d0000A343*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port 20
+
+pci:v00008086d0000A348*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH cAVS
+
+pci:v00008086d0000A352*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH SATA AHCI Controller
+
+pci:v00008086d0000A360*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH HECI Controller
+
+pci:v00008086d0000A36D*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH USB 3.1 xHCI Host Controller
+
+pci:v00008086d0000A36F*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH Shared SRAM
+
+pci:v00008086d0000A370*
+ ID_MODEL_FROM_DATABASE=Wireless-AC 9560 [Jefferson Peak]
+
+pci:v00008086d0000A379*
+ ID_MODEL_FROM_DATABASE=Cannon Lake PCH Thermal Controller
+
pci:v00008086d0000A620*
ID_MODEL_FROM_DATABASE=6400/6402 Advanced Memory Buffer (AMB)
@@ -86042,6 +86768,9 @@ pci:v00008086d0000D157*
pci:v00008086d0000D158*
ID_MODEL_FROM_DATABASE=Core Processor Miscellaneous Registers
+pci:v00008086d0000F1A6*
+ ID_MODEL_FROM_DATABASE=SSD Pro 7600p/760p/E 6100p Series
+
pci:v000080EE*
ID_VENDOR_FROM_DATABASE=InnoTek Systemberatung GmbH
@@ -87443,6 +88172,9 @@ pci:v00009710d00009855sv00001000sd00000022*
pci:v00009710d00009865*
ID_MODEL_FROM_DATABASE=PCI 9865 Multi-I/O Controller
+pci:v00009710d00009900*
+ ID_MODEL_FROM_DATABASE=MCS9900 Multi-I/O Controller
+
pci:v00009710d00009901*
ID_MODEL_FROM_DATABASE=PCIe 9901 Multi-I/O Controller
@@ -87962,6 +88694,9 @@ pci:v0000DCBAd0000004F*
pci:v0000DCBAd00000052*
ID_MODEL_FROM_DATABASE=PCIeBiSerialDb37 BA22 LVDS IO
+pci:v0000DCBAd00000066*
+ ID_MODEL_FROM_DATABASE=PMC-OctalUART-232
+
pci:v0000DD01*
ID_VENDOR_FROM_DATABASE=Digital Devices GmbH
diff --git a/hwdb/20-usb-vendor-model.hwdb b/hwdb/20-usb-vendor-model.hwdb
index 8458828ade..94ac8f2ff1 100644
--- a/hwdb/20-usb-vendor-model.hwdb
+++ b/hwdb/20-usb-vendor-model.hwdb
@@ -29,6 +29,12 @@ usb:v0053*
usb:v0053p5301*
ID_MODEL_FROM_DATABASE=GW-US54ZGL 802.11bg
+usb:v0078*
+ ID_VENDOR_FROM_DATABASE=Microntek
+
+usb:v0078p0006*
+ ID_MODEL_FROM_DATABASE=Joystick
+
usb:v0079*
ID_VENDOR_FROM_DATABASE=DragonRise Inc.
@@ -38,6 +44,24 @@ usb:v0079p0006*
usb:v0079p0011*
ID_MODEL_FROM_DATABASE=Gamepad
+usb:v0079p1800*
+ ID_MODEL_FROM_DATABASE=Mayflash Wii U Pro Game Controller Adapter [DirectInput]
+
+usb:v0079p181B*
+ ID_MODEL_FROM_DATABASE=Venom Arcade Joystick
+
+usb:v0079p1843*
+ ID_MODEL_FROM_DATABASE=Mayflash GameCube Controller Adapter
+
+usb:v0079p1844*
+ ID_MODEL_FROM_DATABASE=Mayflash GameCube Controller
+
+usb:v0085*
+ ID_VENDOR_FROM_DATABASE=Boeye Technology Co., Ltd.
+
+usb:v0085p0600*
+ ID_MODEL_FROM_DATABASE=eBook Reader
+
usb:v0105*
ID_VENDOR_FROM_DATABASE=Trust International B.V.
@@ -92,6 +116,9 @@ usb:v02AD*
usb:v02ADp138C*
ID_MODEL_FROM_DATABASE=PVR Mass Storage
+usb:v0303*
+ ID_VENDOR_FROM_DATABASE=Mini Automation Controller
+
usb:v0324*
ID_VENDOR_FROM_DATABASE=OCZ Technology Inc
@@ -465,7 +492,7 @@ usb:v03EEpFFFF*
ID_MODEL_FROM_DATABASE=Dongle with BlueCore in DFU mode
usb:v03F0*
- ID_VENDOR_FROM_DATABASE=Hewlett-Packard
+ ID_VENDOR_FROM_DATABASE=HP, Inc
usb:v03F0p0004*
ID_MODEL_FROM_DATABASE=DeskJet 895c
@@ -1211,6 +1238,9 @@ usb:v03F0p2B11*
usb:v03F0p2B17*
ID_MODEL_FROM_DATABASE=LaserJet 1020
+usb:v03F0p2B4A*
+ ID_MODEL_FROM_DATABASE=Business Slim Keyboard
+
usb:v03F0p2C12*
ID_MODEL_FROM_DATABASE=Officejet J4680
@@ -1370,6 +1400,9 @@ usb:v03F0p3A11*
usb:v03F0p3A17*
ID_MODEL_FROM_DATABASE=Printing Support
+usb:v03F0p3A1D*
+ ID_MODEL_FROM_DATABASE=hs2340 HSPA+ mobile broadband
+
usb:v03F0p3B02*
ID_MODEL_FROM_DATABASE=PhotoSmart 7150~
@@ -1382,6 +1415,9 @@ usb:v03F0p3B11*
usb:v03F0p3B17*
ID_MODEL_FROM_DATABASE=LaserJet M1005 MFP
+usb:v03F0p3B2A*
+ ID_MODEL_FROM_DATABASE=Color LaserJet MFP M277dw
+
usb:v03F0p3C02*
ID_MODEL_FROM_DATABASE=PhotoSmart 7350
@@ -2309,12 +2345,24 @@ usb:v0403pA9A0*
usb:v0403pABB8*
ID_MODEL_FROM_DATABASE=Lego Mindstorms NXTCam
+usb:v0403pB0C0*
+ ID_MODEL_FROM_DATABASE=microSensys RFID device
+
+usb:v0403pB0C1*
+ ID_MODEL_FROM_DATABASE=microSensys RFID device
+
usb:v0403pB0C2*
ID_MODEL_FROM_DATABASE=iID contactless RFID device
usb:v0403pB0C3*
ID_MODEL_FROM_DATABASE=iID contactless RFID device
+usb:v0403pB0C4*
+ ID_MODEL_FROM_DATABASE=RFID device
+
+usb:v0403pB0C5*
+ ID_MODEL_FROM_DATABASE=RFID device
+
usb:v0403pB810*
ID_MODEL_FROM_DATABASE=US Interface Navigator (CAT and 2nd PTT lines)
@@ -3321,7 +3369,7 @@ usb:v040Bp6510*
ID_MODEL_FROM_DATABASE=Weltrend Bar Code Reader
usb:v040Bp6520*
- ID_MODEL_FROM_DATABASE=XBOX Xploder
+ ID_MODEL_FROM_DATABASE=Xploder Xbox Memory Unit (8MB)
usb:v040Bp6533*
ID_MODEL_FROM_DATABASE=Speed-Link Competition Pro
@@ -4712,6 +4760,12 @@ usb:v0424p2640*
usb:v0424p2660*
ID_MODEL_FROM_DATABASE=Hub
+usb:v0424p274D*
+ ID_MODEL_FROM_DATABASE=HTC Hub Controller
+
+usb:v0424p3FCC*
+ ID_MODEL_FROM_DATABASE=RME MADIface
+
usb:v0424p4041*
ID_MODEL_FROM_DATABASE=Hub and media card controller
@@ -4730,6 +4784,9 @@ usb:v0424p5534*
usb:v0424p7500*
ID_MODEL_FROM_DATABASE=LAN7500 Ethernet 10/100/1000 Adapter
+usb:v0424p9500*
+ ID_MODEL_FROM_DATABASE=LAN9500/LAN9500i
+
usb:v0424p9512*
ID_MODEL_FROM_DATABASE=SMC9512/9514 USB Hub
@@ -4739,6 +4796,9 @@ usb:v0424p9514*
usb:v0424p9904*
ID_MODEL_FROM_DATABASE=LAN9512/LAN9514 Ethernet 10/100 Adapter (SAL10)
+usb:v0424p9E00*
+ ID_MODEL_FROM_DATABASE=LAN9500A/LAN9500Ai
+
usb:v0424pA700*
ID_MODEL_FROM_DATABASE=2 Port Hub
@@ -5519,6 +5579,21 @@ usb:v044Fp0404*
usb:v044Fp044F*
ID_MODEL_FROM_DATABASE=GP XID
+usb:v044Fp0F00*
+ ID_MODEL_FROM_DATABASE=Steering Wheel for Xbox
+
+usb:v044Fp0F03*
+ ID_MODEL_FROM_DATABASE=Steering Wheel for Xbox
+
+usb:v044Fp0F07*
+ ID_MODEL_FROM_DATABASE=Controller for Xbox
+
+usb:v044Fp0F0C*
+ ID_MODEL_FROM_DATABASE=Xbox Memory Unit (8MB)
+
+usb:v044Fp0F10*
+ ID_MODEL_FROM_DATABASE=Modena GT Wheel
+
usb:v044FpA003*
ID_MODEL_FROM_DATABASE=Rage 3D Game Pad
@@ -5570,6 +5645,9 @@ usb:v044FpB323*
usb:v044FpB324*
ID_MODEL_FROM_DATABASE=Dual Trigger 3-in-1 (PS3 Mode)
+usb:v044FpB326*
+ ID_MODEL_FROM_DATABASE=Gamepad GP XID
+
usb:v044FpB603*
ID_MODEL_FROM_DATABASE=force feedback Wheel
@@ -5633,6 +5711,12 @@ usb:v0451p3F00*
usb:v0451p3F02*
ID_MODEL_FROM_DATABASE=SMC WSKP100 Wi-Fi Phone
+usb:v0451p505F*
+ ID_MODEL_FROM_DATABASE=TUSB5052 Serial
+
+usb:v0451p5153*
+ ID_MODEL_FROM_DATABASE=TUSB5052 Hub
+
usb:v0451p5409*
ID_MODEL_FROM_DATABASE=Frontier Labs NEX IA+ Digital Audio Player
@@ -5753,6 +5837,9 @@ usb:v0457p0163*
usb:v0457p0817*
ID_MODEL_FROM_DATABASE=SiS-184-ASUS-4352.17 touch panel
+usb:v0457p10E1*
+ ID_MODEL_FROM_DATABASE=HID Touch Controller
+
usb:v0457p5401*
ID_MODEL_FROM_DATABASE=Wireless Adapter RO80211GS-USB
@@ -6473,6 +6560,9 @@ usb:v045Ep02B0*
usb:v045Ep02B6*
ID_MODEL_FROM_DATABASE=Xbox360 Bluetooth Wireless Headset
+usb:v045Ep02BB*
+ ID_MODEL_FROM_DATABASE=Kinect Audio
+
usb:v045Ep02BE*
ID_MODEL_FROM_DATABASE=Kinect for Windows NUI Audio
@@ -6489,7 +6579,7 @@ usb:v045Ep02D5*
ID_MODEL_FROM_DATABASE=Xbox One Digital TV Tuner
usb:v045Ep02DD*
- ID_MODEL_FROM_DATABASE=Xbox One Controller (Covert Forces/Firmware 2015)
+ ID_MODEL_FROM_DATABASE=Xbox One Controller (Firmware 2015)
usb:v045Ep02E3*
ID_MODEL_FROM_DATABASE=Xbox One Elite Controller
@@ -6500,6 +6590,9 @@ usb:v045Ep02E6*
usb:v045Ep02EA*
ID_MODEL_FROM_DATABASE=Xbox One S Controller
+usb:v045Ep02FD*
+ ID_MODEL_FROM_DATABASE=Xbox One S Controller [Bluetooth]
+
usb:v045Ep0400*
ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002
@@ -6998,15 +7091,48 @@ usb:v045Ep07A5*
usb:v045Ep07B9*
ID_MODEL_FROM_DATABASE=Wired Keyboard 200
+usb:v045Ep07C6*
+ ID_MODEL_FROM_DATABASE=RTL8153 GigE [Surface Dock Ethernet]
+
usb:v045Ep07CA*
ID_MODEL_FROM_DATABASE=Surface Pro 3 Docking Station Audio Device
+usb:v045Ep07CD*
+ ID_MODEL_FROM_DATABASE=Surface Keyboard
+
usb:v045Ep07F8*
ID_MODEL_FROM_DATABASE=Wired Keyboard 600 (model 1576)
usb:v045Ep07FD*
ID_MODEL_FROM_DATABASE=Nano Transceiver 1.1
+usb:v045Ep0900*
+ ID_MODEL_FROM_DATABASE=Surface Dock Hub
+
+usb:v045Ep0901*
+ ID_MODEL_FROM_DATABASE=Surface Dock Hub
+
+usb:v045Ep0902*
+ ID_MODEL_FROM_DATABASE=Surface Dock Hub
+
+usb:v045Ep0903*
+ ID_MODEL_FROM_DATABASE=Surface Dock Hub
+
+usb:v045Ep0904*
+ ID_MODEL_FROM_DATABASE=Surface Dock Extender
+
+usb:v045Ep0905*
+ ID_MODEL_FROM_DATABASE=Surface Dock Audio
+
+usb:v045Ep090B*
+ ID_MODEL_FROM_DATABASE=Hub
+
+usb:v045Ep090C*
+ ID_MODEL_FROM_DATABASE=SD Card
+
+usb:v045Ep091A*
+ ID_MODEL_FROM_DATABASE=Hub
+
usb:v045Ep0A00*
ID_MODEL_FROM_DATABASE=Lumia 950 Dual SIM (RM-1118)
@@ -7208,6 +7334,9 @@ usb:v0461p4D75*
usb:v0461p4D81*
ID_MODEL_FROM_DATABASE=Dell N889 Optical Mouse
+usb:v0461p4DE3*
+ ID_MODEL_FROM_DATABASE=HP 5-Button Optical Comfort Mouse
+
usb:v0461p4DE7*
ID_MODEL_FROM_DATABASE=webcam
@@ -7260,7 +7389,7 @@ usb:v046Ap0021*
ID_MODEL_FROM_DATABASE=CyMotion Expert Combo
usb:v046Ap0023*
- ID_MODEL_FROM_DATABASE=CyMotion Master Linux Keyboard G230
+ ID_MODEL_FROM_DATABASE=Keyboard
usb:v046Ap0027*
ID_MODEL_FROM_DATABASE=CyMotion Master Solar Keyboard
@@ -7289,6 +7418,9 @@ usb:v046Ap0080*
usb:v046Ap0081*
ID_MODEL_FROM_DATABASE=eHealth Keyboard G87 1504
+usb:v046Ap00A1*
+ ID_MODEL_FROM_DATABASE=SmartCard Reader Keyboard KC 1000 SC
+
usb:v046Ap0106*
ID_MODEL_FROM_DATABASE=R-300 Wireless Mouse Receiver
@@ -7334,6 +7466,9 @@ usb:v046Dp0200*
usb:v046Dp0203*
ID_MODEL_FROM_DATABASE=M2452 Keyboard
+usb:v046Dp0242*
+ ID_MODEL_FROM_DATABASE=Chillstream for Xbox 360
+
usb:v046Dp0301*
ID_MODEL_FROM_DATABASE=M4848 Mouse
@@ -7394,6 +7529,9 @@ usb:v046Dp0820*
usb:v046Dp0821*
ID_MODEL_FROM_DATABASE=HD Webcam C910
+usb:v046Dp0823*
+ ID_MODEL_FROM_DATABASE=HD Webcam B910
+
usb:v046Dp0825*
ID_MODEL_FROM_DATABASE=Webcam C270
@@ -8070,13 +8208,13 @@ usb:v046DpC215*
ID_MODEL_FROM_DATABASE=Extreme 3D Pro
usb:v046DpC216*
- ID_MODEL_FROM_DATABASE=Dual Action Gamepad
+ ID_MODEL_FROM_DATABASE=F310 Gamepad [DirectInput Mode]
usb:v046DpC218*
- ID_MODEL_FROM_DATABASE=Logitech RumblePad 2 USB
+ ID_MODEL_FROM_DATABASE=F510 Gamepad [DirectInput Mode]
usb:v046DpC219*
- ID_MODEL_FROM_DATABASE=Cordless RumblePad 2
+ ID_MODEL_FROM_DATABASE=F710 Gamepad [DirectInput Mode]
usb:v046DpC21A*
ID_MODEL_FROM_DATABASE=Precision Gamepad
@@ -8501,12 +8639,27 @@ usb:v046DpCA03*
usb:v046DpCA04*
ID_MODEL_FROM_DATABASE=Formula Vibration Feedback Wheel
+usb:v046DpCA84*
+ ID_MODEL_FROM_DATABASE=Cordless Controller for Xbox
+
+usb:v046DpCA88*
+ ID_MODEL_FROM_DATABASE=Thunderpad for Xbox
+
+usb:v046DpCA8A*
+ ID_MODEL_FROM_DATABASE=Precision Vibration Feedback Wheel for Xbox
+
+usb:v046DpCAA3*
+ ID_MODEL_FROM_DATABASE=DriveFX Racing Wheel
+
usb:v046DpCAB1*
ID_MODEL_FROM_DATABASE=Cordless Keyboard for Wii HID Receiver
usb:v046DpD001*
ID_MODEL_FROM_DATABASE=QuickCam Pro
+usb:v046DpF301*
+ ID_MODEL_FROM_DATABASE=Controller
+
usb:v046E*
ID_VENDOR_FROM_DATABASE=Behavior Tech. Computer Corp.
@@ -8858,6 +9011,9 @@ usb:v0471p20E4*
usb:v0471p2160*
ID_MODEL_FROM_DATABASE=Mio LINK Heart Rate Monitor
+usb:v0471p21E0*
+ ID_MODEL_FROM_DATABASE=GoGEAR Raga
+
usb:v0471p262C*
ID_MODEL_FROM_DATABASE=SPC230NC Webcam
@@ -9368,6 +9524,9 @@ usb:v0482p0204*
usb:v0482p0408*
ID_MODEL_FROM_DATABASE=FS-1320D Printer
+usb:v0482p0640*
+ ID_MODEL_FROM_DATABASE=ECOSYS M6026cdn
+
usb:v0482p069B*
ID_MODEL_FROM_DATABASE=ECOSYS M2635dn
@@ -9429,16 +9588,22 @@ usb:v0483p5710*
ID_MODEL_FROM_DATABASE=Joystick in FS Mode
usb:v0483p5720*
- ID_MODEL_FROM_DATABASE=STM microSD Flash Device
+ ID_MODEL_FROM_DATABASE=Mass Storage Device
usb:v0483p5721*
ID_MODEL_FROM_DATABASE=Hantek DDS-3X25 Arbitrary Waveform Generator
+usb:v0483p5722*
+ ID_MODEL_FROM_DATABASE=Bulk Demo
+
usb:v0483p5730*
- ID_MODEL_FROM_DATABASE=STM32 Audio Streaming
+ ID_MODEL_FROM_DATABASE=Audio Speaker
+
+usb:v0483p5731*
+ ID_MODEL_FROM_DATABASE=Microphone
usb:v0483p5740*
- ID_MODEL_FROM_DATABASE=STM32F407
+ ID_MODEL_FROM_DATABASE=Virtual COM Port
usb:v0483p7270*
ID_MODEL_FROM_DATABASE=ST Micro Serial Bridge
@@ -9446,9 +9611,18 @@ usb:v0483p7270*
usb:v0483p7554*
ID_MODEL_FROM_DATABASE=56k SoftModem
+usb:v0483p8213*
+ ID_MODEL_FROM_DATABASE=ThermaData Logger Cradle
+
+usb:v0483p8259*
+ ID_MODEL_FROM_DATABASE=Probe
+
usb:v0483p91D1*
ID_MODEL_FROM_DATABASE=Sensor Hub
+usb:v0483pA171*
+ ID_MODEL_FROM_DATABASE=ThermaData WiFi
+
usb:v0483pDF11*
ID_MODEL_FROM_DATABASE=STM Device in DFU Mode
@@ -9518,6 +9692,9 @@ usb:v0489pE042*
usb:v0489pE04D*
ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth
+usb:v0489pE055*
+ ID_MODEL_FROM_DATABASE=BCM43142A0 broadcom bluetooth
+
usb:v048A*
ID_VENDOR_FROM_DATABASE=S-MOS Systems, Inc.
@@ -10322,6 +10499,9 @@ usb:v04A7p04A0*
usb:v04A7p04AC*
ID_MODEL_FROM_DATABASE=Xerox Travel Scanner 100
+usb:v04A7p04BB*
+ ID_MODEL_FROM_DATABASE=strobe 400 scanner
+
usb:v04A7p04CD*
ID_MODEL_FROM_DATABASE=Xerox Travel Scanner 150
@@ -10586,6 +10766,9 @@ usb:v04A9p1608*
usb:v04A9p1609*
ID_MODEL_FROM_DATABASE=DR-3080CII
+usb:v04A9p160A*
+ ID_MODEL_FROM_DATABASE=DR-2050C Scanner
+
usb:v04A9p1700*
ID_MODEL_FROM_DATABASE=PIXMA MP110 Scanner
@@ -11075,6 +11258,9 @@ usb:v04A9p2629*
usb:v04A9p262B*
ID_MODEL_FROM_DATABASE=LaserShot LBP-1120 Printer
+usb:v04A9p262C*
+ ID_MODEL_FROM_DATABASE=imageCLASS D300
+
usb:v04A9p262D*
ID_MODEL_FROM_DATABASE=iR C3200
@@ -11090,6 +11276,12 @@ usb:v04A9p2631*
usb:v04A9p2632*
ID_MODEL_FROM_DATABASE=FAX-L2000
+usb:v04A9p2633*
+ ID_MODEL_FROM_DATABASE=LASERCLASS 500
+
+usb:v04A9p2634*
+ ID_MODEL_FROM_DATABASE=PC-D300/FAX-L400/ICD300
+
usb:v04A9p2635*
ID_MODEL_FROM_DATABASE=MPC190
@@ -11252,6 +11444,9 @@ usb:v04A9p2688*
usb:v04A9p2689*
ID_MODEL_FROM_DATABASE=FAX-L180/L380S/L398S
+usb:v04A9p268A*
+ ID_MODEL_FROM_DATABASE=LC310/L390/L408S
+
usb:v04A9p268C*
ID_MODEL_FROM_DATABASE=iR C6870
@@ -11816,6 +12011,9 @@ usb:v04A9p3195*
usb:v04A9p3196*
ID_MODEL_FROM_DATABASE=PowerShot SD880 IS DIGITAL ELPH / Digital IXUS 870 IS / IXY DIGITAL 920 IS
+usb:v04A9p3199*
+ ID_MODEL_FROM_DATABASE=EOS 5D Mark II
+
usb:v04A9p319A*
ID_MODEL_FROM_DATABASE=EOS 7D
@@ -12236,6 +12434,9 @@ usb:v04A9p32C2*
usb:v04A9p32D5*
ID_MODEL_FROM_DATABASE=PowerShot SX430 IS
+usb:v04A9p32DB*
+ ID_MODEL_FROM_DATABASE=SELPHY CP1300
+
usb:v04AA*
ID_VENDOR_FROM_DATABASE=DaeWoo Telecom, Ltd
@@ -12662,6 +12863,15 @@ usb:v04B4p5A9B*
usb:v04B4p6370*
ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201
+usb:v04B4p6502*
+ ID_MODEL_FROM_DATABASE=CY4609
+
+usb:v04B4p6506*
+ ID_MODEL_FROM_DATABASE=CY4603
+
+usb:v04B4p650A*
+ ID_MODEL_FROM_DATABASE=CY4613
+
usb:v04B4p6560*
ID_MODEL_FROM_DATABASE=CY7C65640 USB-2.0 "TetraHub"
@@ -12713,6 +12923,9 @@ usb:v04B4pF111*
usb:v04B4pF115*
ID_MODEL_FROM_DATABASE=PSoC FirstTouch Programmer
+usb:v04B4pF231*
+ ID_MODEL_FROM_DATABASE=DELLY Changer 4in1 universal IR remote
+
usb:v04B4pF232*
ID_MODEL_FROM_DATABASE=Mono embedded computer
@@ -13685,6 +13898,9 @@ usb:v04CAp300F*
usb:v04CAp3014*
ID_MODEL_FROM_DATABASE=Qualcomm Atheros Bluetooth
+usb:v04CAp7022*
+ ID_MODEL_FROM_DATABASE=HP HD Webcam
+
usb:v04CAp7025*
ID_MODEL_FROM_DATABASE=HP HD Webcam
@@ -13722,7 +13938,7 @@ usb:v04CBp010B*
ID_MODEL_FROM_DATABASE=FinePix S602 (Pro) Zoom (PC CAM)
usb:v04CBp010D*
- ID_MODEL_FROM_DATABASE=FinePix Digital Camera 020531
+ ID_MODEL_FROM_DATABASE=FinePix S2 pro
usb:v04CBp010E*
ID_MODEL_FROM_DATABASE=FinePix F402 Zoom (DSC)
@@ -14147,6 +14363,9 @@ usb:v04D8p9004*
usb:v04D8p900A*
ID_MODEL_FROM_DATABASE=PICkit3
+usb:v04D8p9012*
+ ID_MODEL_FROM_DATABASE=PICkit4
+
usb:v04D8pC001*
ID_MODEL_FROM_DATABASE=PicoLCD 20x4
@@ -14267,6 +14486,9 @@ usb:v04D9pA01C*
usb:v04D9pA050*
ID_MODEL_FROM_DATABASE=Chatman V1
+usb:v04D9pA052*
+ ID_MODEL_FROM_DATABASE=USB-zyTemp
+
usb:v04D9pA055*
ID_MODEL_FROM_DATABASE=Keyboard
@@ -14972,6 +15194,9 @@ usb:v04E8p326C*
usb:v04E8p3276*
ID_MODEL_FROM_DATABASE=ML-3050/ML-3051 Laser Printer
+usb:v04E8p327E*
+ ID_MODEL_FROM_DATABASE=ML-2510 Series
+
usb:v04E8p328E*
ID_MODEL_FROM_DATABASE=CLP-310 Color Laser Printer
@@ -15299,6 +15524,9 @@ usb:v04E8p61B6*
usb:v04E8p61F3*
ID_MODEL_FROM_DATABASE=Portable SSD T3 (MU-PT250B, MU-PT500B)
+usb:v04E8p61F5*
+ ID_MODEL_FROM_DATABASE=Portable SSD T5
+
usb:v04E8p6601*
ID_MODEL_FROM_DATABASE=Mobile Phone
@@ -15599,6 +15827,9 @@ usb:v04F2p0718*
usb:v04F2p0760*
ID_MODEL_FROM_DATABASE=Acer KU-0760 Keyboard
+usb:v04F2p0833*
+ ID_MODEL_FROM_DATABASE=KU-0833 Keyboard
+
usb:v04F2p0841*
ID_MODEL_FROM_DATABASE=HP Multimedia Keyboard
@@ -15755,6 +15986,9 @@ usb:v04F2pB175*
usb:v04F2pB1AA*
ID_MODEL_FROM_DATABASE=Webcam-101
+usb:v04F2pB1AC*
+ ID_MODEL_FROM_DATABASE=HP Laptop Integrated Webcam [2 MP Fixed]
+
usb:v04F2pB1B4*
ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera
@@ -15803,9 +16037,15 @@ usb:v04F2pB2B9*
usb:v04F2pB2DA*
ID_MODEL_FROM_DATABASE=thinkpad t430s camera
+usb:v04F2pB2DB*
+ ID_MODEL_FROM_DATABASE=Thinkpad T430 camera
+
usb:v04F2pB2EA*
ID_MODEL_FROM_DATABASE=Integrated Camera [ThinkPad]
+usb:v04F2pB2F4*
+ ID_MODEL_FROM_DATABASE=HP Webcam-50
+
usb:v04F2pB330*
ID_MODEL_FROM_DATABASE=Asus 720p CMOS webcam
@@ -15830,6 +16070,12 @@ usb:v04F2pB40E*
usb:v04F2pB444*
ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam
+usb:v04F2pB5CE*
+ ID_MODEL_FROM_DATABASE=Integrated Camera
+
+usb:v04F2pB5CF*
+ ID_MODEL_FROM_DATABASE=Integrated IR Camera
+
usb:v04F3*
ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp.
@@ -15866,6 +16112,9 @@ usb:v04F3p0232*
usb:v04F3p0234*
ID_MODEL_FROM_DATABASE=Optical Mouse
+usb:v04F3p0235*
+ ID_MODEL_FROM_DATABASE=Optical Mouse
+
usb:v04F3p02F4*
ID_MODEL_FROM_DATABASE=2.4G Cordless Mouse
@@ -18156,7 +18405,7 @@ usb:v0525pA4A4*
ID_MODEL_FROM_DATABASE=Linux-USB user-mode bulk source/sink
usb:v0525pA4A5*
- ID_MODEL_FROM_DATABASE=Pocketbook Pro 903
+ ID_MODEL_FROM_DATABASE=Pocketbook Pro 903 / Mobius 2 Action Cam
usb:v0525pA4A6*
ID_MODEL_FROM_DATABASE=Linux-USB Serial Gadget
@@ -18594,7 +18843,7 @@ usb:v054Cp0002*
ID_MODEL_FROM_DATABASE=Standard HUB
usb:v054Cp0010*
- ID_MODEL_FROM_DATABASE=DSC-S30/S70/S75/F505V/F505/FD92/W1 Cybershot/Mavica Digital Camera
+ ID_MODEL_FROM_DATABASE=Cyber-shot, Mavica (msc)
usb:v054Cp0014*
ID_MODEL_FROM_DATABASE=Nogatech USBVision (SY)
@@ -19125,7 +19374,7 @@ usb:v054Cp0541*
ID_MODEL_FROM_DATABASE=DSC-HX100V [Cybershot Digital Still Camera]
usb:v054Cp05C4*
- ID_MODEL_FROM_DATABASE=DualShock 4 [CUH-ZCT1E]
+ ID_MODEL_FROM_DATABASE=DualShock 4 [CUH-ZCT1x]
usb:v054Cp0689*
ID_MODEL_FROM_DATABASE=Walkman NWZ-B173F
@@ -19139,6 +19388,9 @@ usb:v054Cp06C3*
usb:v054Cp07C4*
ID_MODEL_FROM_DATABASE=ILCE-6000 (aka Alpha-6000) in Mass Storage mode
+usb:v054Cp082F*
+ ID_MODEL_FROM_DATABASE=Walkman NWZW Series
+
usb:v054Cp0847*
ID_MODEL_FROM_DATABASE=WG-C10 Portable Wireless Server
@@ -19155,7 +19407,10 @@ usb:v054Cp0994*
ID_MODEL_FROM_DATABASE=ILCE-6000 (aka Alpha-6000) in charging mode
usb:v054Cp09CC*
- ID_MODEL_FROM_DATABASE=DualShock 4 [CUH-ZCT2E]
+ ID_MODEL_FROM_DATABASE=DualShock 4 [CUH-ZCT2x]
+
+usb:v054Cp0BA0*
+ ID_MODEL_FROM_DATABASE=Dualshock4 Wireless Adaptor
usb:v054Cp0BB5*
ID_MODEL_FROM_DATABASE=Headset MDR-1000X
@@ -19472,6 +19727,9 @@ usb:v055Fp0409*
usb:v055Fp040B*
ID_MODEL_FROM_DATABASE=ScanExpress A3 USB 1200 PRO
+usb:v055Fp0501*
+ ID_MODEL_FROM_DATABASE=ScanExpress A3 2400 Pro
+
usb:v055Fp0873*
ID_MODEL_FROM_DATABASE=ScanExpress 600 USB
@@ -20048,12 +20306,24 @@ usb:v056Ap034F*
usb:v056Ap0350*
ID_MODEL_FROM_DATABASE=DTH-1620 [Cintiq Pro 16] tablet
+usb:v056Ap0351*
+ ID_MODEL_FROM_DATABASE=DTH-2420 [Cintiq Pro 24 PT] tablet
+
+usb:v056Ap0352*
+ ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] tablet
+
usb:v056Ap0353*
ID_MODEL_FROM_DATABASE=DTH-1320 [Cintiq Pro 13] touchscreen
usb:v056Ap0354*
ID_MODEL_FROM_DATABASE=DTH-1620 [Cintiq Pro 16] touchscreen
+usb:v056Ap0355*
+ ID_MODEL_FROM_DATABASE=DTH-2420 [Cintiq Pro 24 PT] touchscreen
+
+usb:v056Ap0356*
+ ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] touchscreen
+
usb:v056Ap0357*
ID_MODEL_FROM_DATABASE=PTH-660 [Intuos Pro (M)]
@@ -20066,6 +20336,48 @@ usb:v056Ap035A*
usb:v056Ap0368*
ID_MODEL_FROM_DATABASE=DTH-1152 touchscreen
+usb:v056Ap0374*
+ ID_MODEL_FROM_DATABASE=CTL-4100 [Intuos (S)]
+
+usb:v056Ap0375*
+ ID_MODEL_FROM_DATABASE=CTL-6100 [Intuos (M)]
+
+usb:v056Ap0376*
+ ID_MODEL_FROM_DATABASE=CTL-4100WL [Intuos BT (S)]
+
+usb:v056Ap0378*
+ ID_MODEL_FROM_DATABASE=CTL-6100WL [Intuos BT (M)]
+
+usb:v056Ap037A*
+ ID_MODEL_FROM_DATABASE=CTL-472 [One by Wacom (S)]
+
+usb:v056Ap037B*
+ ID_MODEL_FROM_DATABASE=CTL-672 [One by Wacom (M)]
+
+usb:v056Ap037C*
+ ID_MODEL_FROM_DATABASE=DTK-2420 [Cintiq Pro 24 P]
+
+usb:v056Ap037D*
+ ID_MODEL_FROM_DATABASE=DTH-2452 tablet
+
+usb:v056Ap037E*
+ ID_MODEL_FROM_DATABASE=DTH-2452 touchscreen
+
+usb:v056Ap0382*
+ ID_MODEL_FROM_DATABASE=DTK-2451 tablet
+
+usb:v056Ap038A*
+ ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] internal hub
+
+usb:v056Ap038D*
+ ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] internal hub
+
+usb:v056Ap038E*
+ ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] external hub
+
+usb:v056Ap038F*
+ ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] internal hub
+
usb:v056Ap0400*
ID_MODEL_FROM_DATABASE=PenPartner 4x5
@@ -20129,8 +20441,35 @@ usb:v056Ep0002*
usb:v056Ep0057*
ID_MODEL_FROM_DATABASE=M-PGDL Mouse
+usb:v056Ep005C*
+ ID_MODEL_FROM_DATABASE=M-PGDL Mouse
+
+usb:v056Ep005D*
+ ID_MODEL_FROM_DATABASE=M-FGDL Mouse
+
+usb:v056Ep005E*
+ ID_MODEL_FROM_DATABASE=M-FG2DL Mouse
+
+usb:v056Ep0062*
+ ID_MODEL_FROM_DATABASE=M-D18DR Mouse
+
+usb:v056Ep0063*
+ ID_MODEL_FROM_DATABASE=M-SODL Mouse
+
+usb:v056Ep0069*
+ ID_MODEL_FROM_DATABASE=M-GE1UL Mouse
+
+usb:v056Ep0071*
+ ID_MODEL_FROM_DATABASE=M-GE3DL Mouse
+
usb:v056Ep0072*
- ID_MODEL_FROM_DATABASE=Mouse
+ ID_MODEL_FROM_DATABASE=M-LS6UL Mouse
+
+usb:v056Ep0073*
+ ID_MODEL_FROM_DATABASE=M-LS7UL Mouse
+
+usb:v056Ep0074*
+ ID_MODEL_FROM_DATABASE=M-FW1UL Mouse
usb:v056Ep200C*
ID_MODEL_FROM_DATABASE=LD-USB/TX
@@ -55344,16 +55683,19 @@ usb:v20F7*
ID_VENDOR_FROM_DATABASE=XIMEA
usb:v20F7p3001*
- ID_MODEL_FROM_DATABASE=Camera with CMOS sensor [MQ]
+ ID_MODEL_FROM_DATABASE=MQ or MD camera
+
+usb:v20F7p3002*
+ ID_MODEL_FROM_DATABASE=MU camera
usb:v20F7p3021*
- ID_MODEL_FROM_DATABASE=Camera with CCD sensor [MD]
+ ID_MODEL_FROM_DATABASE=MJ camera
usb:v20F7p30B3*
- ID_MODEL_FROM_DATABASE=Camera with CMOS sensor in Vision mode [MQ]
+ ID_MODEL_FROM_DATABASE=MQ in U3V mode or MC camera
usb:v20F7pA003*
- ID_MODEL_FROM_DATABASE=Subminiature 5Mpix B/W Camera, MU9PM-MH
+ ID_MODEL_FROM_DATABASE=MU camera
usb:v2100*
ID_VENDOR_FROM_DATABASE=RT Systems
@@ -55997,6 +56339,42 @@ usb:v2341p0045*
usb:v2341p8036*
ID_MODEL_FROM_DATABASE=Leonardo (CDC ACM, HID)
+usb:v2357*
+ ID_VENDOR_FROM_DATABASE=TP-Link
+
+usb:v2357p0100*
+ ID_MODEL_FROM_DATABASE=TL-WN8200ND [Realtek RTL8192CU]
+
+usb:v2357p0101*
+ ID_MODEL_FROM_DATABASE=RTL8812AU Archer T4U 802.11ac
+
+usb:v2357p0103*
+ ID_MODEL_FROM_DATABASE=Archer T4UH wireless Realtek 8812AU
+
+usb:v2357p0105*
+ ID_MODEL_FROM_DATABASE=Archer T1U 802.11a/n/ac Wireless Adapter [MediaTek MT7610U]
+
+usb:v2357p0107*
+ ID_MODEL_FROM_DATABASE=TL-WN821N Version 5 RTL8192EU
+
+usb:v2357p0108*
+ ID_MODEL_FROM_DATABASE=TL-WN822N Version 4 RTL8192EU
+
+usb:v2357p0109*
+ ID_MODEL_FROM_DATABASE=TL WN823N RTL8192EU
+
+usb:v2357p010C*
+ ID_MODEL_FROM_DATABASE=TL-WN722N v2
+
+usb:v2357p010E*
+ ID_MODEL_FROM_DATABASE=TL-WN722N v2
+
+usb:v2357p0200*
+ ID_MODEL_FROM_DATABASE=MA 180 Zero CD
+
+usb:v2357p0201*
+ ID_MODEL_FROM_DATABASE=HSUPA Modem MA180
+
usb:v2373*
ID_VENDOR_FROM_DATABASE=Pumatronix Ltda
@@ -56573,6 +56951,30 @@ usb:v2C1A*
usb:v2C1Ap0000*
ID_MODEL_FROM_DATABASE=Wireless Optical Mouse
+usb:v2C7C*
+ ID_VENDOR_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd.
+
+usb:v2C7Cp0121*
+ ID_MODEL_FROM_DATABASE=EC21 LTE modem
+
+usb:v2C7Cp0125*
+ ID_MODEL_FROM_DATABASE=EC25 LTE modem
+
+usb:v2C7Cp0191*
+ ID_MODEL_FROM_DATABASE=EG91 LTE modem
+
+usb:v2C7Cp0195*
+ ID_MODEL_FROM_DATABASE=EG95 LTE modem
+
+usb:v2C7Cp0296*
+ ID_MODEL_FROM_DATABASE=BG96 CAT-M1/NB-IoT modem
+
+usb:v2C7Cp0306*
+ ID_MODEL_FROM_DATABASE=EG06/EP06/EM06 LTE-A modem
+
+usb:v2C7Cp0435*
+ ID_MODEL_FROM_DATABASE=AG35 LTE modem
+
usb:v2DCF*
ID_VENDOR_FROM_DATABASE=Dialog Semiconductor
diff --git a/hwdb/20-vmbus-class.hwdb b/hwdb/20-vmbus-class.hwdb
new file mode 100644
index 0000000000..ba96b383a9
--- /dev/null
+++ b/hwdb/20-vmbus-class.hwdb
@@ -0,0 +1,57 @@
+# This file is part of systemd.
+#
+# Data extracted from Linux hyperv.h
+
+vmbus:02780ada77e3ac4a8e770558eb1073f8
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Video
+
+vmbus:1657e6f8b33c064a9a601889c5cccab5
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Remote Desktop Control
+
+vmbus:1df6c444444400449d52802e27ede19f
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V PCI Controller
+
+vmbus:292efa3523ea364296ae3a6ebacba440
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Backup/Restore
+
+vmbus:30e62795aed07b49adcee80ab0175caf
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Time Sync
+
+vmbus:31600b0e13523449818b38d90ced39db
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Guest Shutdown
+
+vmbus:32264132cb86a2449b5c50d1417354f5
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V IDE Controller
+
+vmbus:394f16571591784eab55382f3bd5422d
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Heartbeat
+
+vmbus:3daf2e8ca732094bab99bd1f1c86b501
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Guest RDMA
+
+vmbus:635161f83edfc546913ff2d2f965ed0e
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Network Adapter
+
+vmbus:6dad12f9172bea48bd65f927a61c7684
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Keyboard
+
+vmbus:9eb6a8cf4a5bc04cb98b8ba1a1f3f95a
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Mouse
+
+vmbus:d96361baa104294db60572e2ffb1dc7f
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V SCSI Controller
+
+vmbus:dc7450528589e2468057a307dc18a502
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Dynamic Memory
+
+vmbus:e34bd134e4dec8419ae76b174977c192
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V File Copy
+
+vmbus:e7f4a0a9455a964db8278a841e8c03e6
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Data Exchange
+
+vmbus:f4ac6a2715ac6c4298dd7521ad3f01fe
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Remote Desktop Virtualization
+
+vmbus:f4ba7533159e304bb76567acb10d607b
+ ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Virtual Machine Activation
diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb
index 532a1cc59c..ab4b3068e6 100644
--- a/hwdb/60-evdev.hwdb
+++ b/hwdb/60-evdev.hwdb
@@ -423,6 +423,13 @@ evdev:name:1A586753:00 06CB:8323 Touchpad:dmi:*svnRazer:pnBladeStealth:*
EVDEV_ABS_35=::12:8
EVDEV_ABS_36=::11:8
+# Razer Blade Stealth (2016)
+evdev:name:Synaptics TM2438-005:dmi:*svnRazer:pnBladeStealth*
+ EVDEV_ABS_00=0:4064:29
+ EVDEV_ABS_01=0:2405:37
+ EVDEV_ABS_35=0:4064:29
+ EVDEV_ABS_36=0:2405:37
+
#########################################
# Samsung
#########################################
@@ -469,17 +476,6 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnTOSHIBA:pnSATELLITER830*
EVDEV_ABS_36=1045:4826:76
#########################################
-# Razer
-#########################################
-
-# Razer Blade Stealth (2016)
-evdev:name:Synaptics TM2438-005:dmi:*svnRazer:pnBladeStealth*
- EVDEV_ABS_00=0:4064:29
- EVDEV_ABS_01=0:2405:37
- EVDEV_ABS_35=0:4064:29
- EVDEV_ABS_36=0:2405:37
-
-#########################################
# Waltop
#########################################
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
index 2e24c86663..ae3ec3ca15 100644
--- a/hwdb/60-keyboard.hwdb
+++ b/hwdb/60-keyboard.hwdb
@@ -484,10 +484,6 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*Pavilion*dv7*Notebook*PC:
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*13*x360*:pvr*
KEYBOARD_KEY_d7=unknown
-# Purism Librem 13 V2
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v2*:pvr*
- KEYBOARD_KEY_56=backslash
-
# Elitebook
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Compaq*:pvr*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*EliteBook*:pvr*
@@ -570,6 +566,10 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook*:pvr*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHPZBook*:pvr*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
+# HP ZBook Studio G4
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnHPZBookStudioG4:pvr*
+ KEYBOARD_KEY_f8=wlan # Wireless HW switch button
+
# HP Folio 1040g2
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPEliteBookFolio1040G2:pvr*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
@@ -1053,6 +1053,18 @@ evdev:input:b0003v047FpC006*
KEYBOARD_KEY_b002f=f20 # Microphone mute button; should be micmute
###########################################################
+# Purism
+###########################################################
+
+# Purism Librem 13 V2
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v2*:pvr*
+ KEYBOARD_KEY_56=backslash
+
+# Purism Librem 13 V3
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v3*:pvr*
+ KEYBOARD_KEY_56=backslash
+
+###########################################################
# Quanta
###########################################################
diff --git a/hwdb/60-sensor.hwdb b/hwdb/60-sensor.hwdb
index d7204422bc..36d13e68ca 100644
--- a/hwdb/60-sensor.hwdb
+++ b/hwdb/60-sensor.hwdb
@@ -58,6 +58,12 @@ sensor:modalias:acpi:BMA250E*:dmi:*:svnAcer:pnIconiaW1-810:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
#########################################
+# Archos
+#########################################
+sensor:modalias:acpi:SMO8500*:dmi:*:svnARCHOS:pnARCHOS80Cesium:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+
+#########################################
# AsusTek
#########################################
sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100CHI*
@@ -123,6 +129,7 @@ sensor:modalias:acpi:KIOX000A*:dmi:svnChuwi*:pnHi13
# match the entire dmi-alias, assuming that the use of a BOSC0200 +
# bios-version + bios-date combo is unique
sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/07/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
+sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/28/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
#########################################
@@ -141,6 +148,16 @@ sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni7Stylus:*
sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni16:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+# Cube i7 Stylus I8L Model
+sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni8-L:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+
+#########################################
+# Cytrix (Mytrix)
+#########################################
+sensor:modalias:acpi:*KIOX000A*:dmi:*svn*CytrixTechnology:*pn*Complex11t*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+
#########################################
# Endless
#########################################
@@ -180,6 +197,16 @@ sensor:modalias:acpi:SMO8500*:dmi:*:svnHewlett-Packard:pnHPStream8Tablet:*
sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:*:svnTobefilledbyO.E.M.:pnTW891:pvrTobefilledbyO.E.M.:rvnTobefilledbyO.E.M.:rnTW891:rvr1.0:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+# I.T.Works TW701 7" windows tablet, same hw as Trekstor ST70416-6
+sensor:modalias:acpi:BMA250*:dmi:*:bvritWORKS.G.WI71C.JGBMRB*:*:svnInsyde:pni71c:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+
+#########################################
+# iOTA 360
+#########################################
+sensor:modalias:acpi:KIOX000A*:dmi:*svn*iOTA*:*pn*IOTA2210*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
#########################################
# Jumper
#########################################
@@ -220,8 +247,45 @@ sensor:modalias:acpi:BOSC0200:BOSC0200:dmi:*ThinkPadYoga11e3rdGen*
sensor:modalias:acpi:BMA250E*:dmi:bvnLENOVO:*:pvrLenovoMIIX3-1030:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
-# IdeaPad Miix 320
+# IdeaPad Miix 310 note this only is for BIOS version (bvr) 1HCN4?WW, which has
+# a portrait LCD panel, versions with bvr 1HCN3?WW have a landscape panel
+sensor:modalias:acpi:KIOX000A*:dmi:bvnLENOVO:bvr1HCN4?WW:*:svnLENOVO:pn80SG:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+
+# IdeaPad Miix 320, different batches use a different sensor
sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80XF:*
+sensor:modalias:acpi:SMO8840*:dmi:*:svnLENOVO:pn80XF:pvrLenovoMIIX320*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
+# IdeaPad Miix 510
+sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80XE:*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
+#########################################
+# LINX
+#########################################
+
+# Linx 1010B
+sensor:modalias:acpi:BOSC0200*:dmi:*:svnLINX*:pnLINX1010B:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, -1
+
+#########################################
+# MSI
+#########################################
+sensor:modalias:acpi:SMO8500*:dmi:*:svnMicro-StarInternationalCo.,Ltd.:pnS100:*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1
+
+#########################################
+# Nuvision (TMax)
+#########################################
+sensor:modalias:acpi:KIOX000A*:dmi:*:svnTMAX:pnTM800W560L:*
+ ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
+
+#########################################
+# Onda
+#########################################
+sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrONDA.D89*:svnInsyde:pnONDATablet:*
+sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrONDA.W89*:svnInsyde:pnONDATablet:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
#########################################
@@ -236,6 +300,10 @@ sensor:modalias:acpi:SMO8500*:dmi:*:svnPEAQ:pnPEAQPMMC1010MD99187:*
sensor:modalias:acpi:KIOX000A*:dmi:*:svnPIPO:pnW2S:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
+# Pipo W4
+sensor:modalias:acpi:SMO8500*:dmi:*:bvrV8L_WIN32_CHIPHD_*_DX:*:rvnAMICorporation:rnAptioCRB:*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
#########################################
# Ployer
#########################################
@@ -250,6 +318,7 @@ sensor:modalias:acpi:BMA250E*:dmi:*:svnShenzhenPLOYER*:pnMOMO7W:*
# match the entire dmi-alias, assuming that the use of a BMA250E +
# bios-version + bios-date combo is unique
sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1013:bd08/22/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
+sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1014:bd10/24/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
#########################################
@@ -269,14 +338,7 @@ sensor:modalias:acpi:BMA250*:dmi:*:bvrTREK.G.WI71C.JGBMRBA*:*:svnTrekStor:pnSurf
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
#########################################
-# Cytrix (Mytrix)
-#########################################
-sensor:modalias:acpi:*KIOX000A*:dmi:*svn*CytrixTechnology:*pn*Complex11t*
- ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
-
-#########################################
-# iOTA 360
+# Yours
#########################################
-sensor:modalias:acpi:KIOX000A*:dmi:*svn*iOTA*:*pn*IOTA2210*
+sensor:modalias:acpi:BMA250E*:dmi:*:svnYOURS:pnY8W81:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
-
diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb
index 33d01f158a..5adf793752 100644
--- a/hwdb/70-mouse.hwdb
+++ b/hwdb/70-mouse.hwdb
@@ -316,6 +316,11 @@ mouse:usb:v17efp6045:name:Lenovo USB Laser Mouse:
# model name. The usb vid/pid is the same for all those devices.
# Until 3.19 is available, this list just has the Wireless PID entry.
+# Logitech Anywhere MX
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:1017:
+mouse:usb:v046dp1017:name:Logitech Anywhere MX:
+ MOUSE_WHEEL_CLICK_ANGLE=20
+
# Logitech M-BJ58 Optical Mouse
mouse:usb:v046dpc00e:name:Logitech USB-PS/2 Optical Mouse:
# Logitech Mini Optical Mouse
@@ -377,7 +382,7 @@ mouse:usb:v046dp1025:name:Logitech M510:
# Logitech M705 (marathon mouse)
mouse:usb:v046dp101b:name:Logitech M705:
mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101b:
- MOUSE_DPI=800@166
+ MOUSE_DPI=1000@125
# Logitech MX Revolution
mouse:usb:v046dpc51a:name:Logitech USB Receiver:
diff --git a/hwdb/acpi_id_registry.html b/hwdb/acpi_id_registry.html
index df9158ba8c..e1153b0133 100644
--- a/hwdb/acpi_id_registry.html
+++ b/hwdb/acpi_id_registry.html
@@ -85,6 +85,7 @@
<tr class="odd"><td>IHSE GmbH</td><td>IHSE</td><td>06/22/2017</td> </tr>
<tr class="even"><td>Insyde Software</td><td>INSY</td><td>11/10/2017</td> </tr>
<tr class="odd"><td>Nexstgo Company Limited</td><td>NXGO</td><td>11/13/2017</td> </tr>
+ <tr class="even"><td>Ampere Computing</td><td>AMPC</td><td>03/29/2018</td> </tr>
</tbody>
</table>
</body>
diff --git a/hwdb/ma-large.txt b/hwdb/ma-large.txt
index 7d22e6f60d..0ad82a2c1e 100644
--- a/hwdb/ma-large.txt
+++ b/hwdb/ma-large.txt
@@ -1682,12 +1682,6 @@ F85B9C (base 16) SB SYSTEMS Co.,Ltd
Kaohsiung Taiwan 82151
TW
-30-0E-E3 (hex) Aquantia Corporation
-300EE3 (base 16) Aquantia Corporation
- 700 Tasman Drive
- Milpitas CA 95035
- US
-
84-73-03 (hex) Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd.
847303 (base 16) Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd.
5th floor,Hongchengxintai building,No.105,Yaojiayuan Road,Chaoyang District,Beijing
@@ -2207,12 +2201,6 @@ B47C29 (base 16) Shenzhen Guzidi Technology Co.,Ltd
Taoyuan Hsien Chungli 320
TW
-DC-39-79 (hex) Skyport Systems
-DC3979 (base 16) Skyport Systems
- 280 Hope Street
- Mountain View CA 94041
- US
-
EC-1D-7F (hex) zte corporation
EC1D7F (base 16) zte corporation
12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
@@ -2255,12 +2243,6 @@ F42853 (base 16) Zioncom Electronics (Shenzhen) Ltd.
Shenzhen Guangdong 518000
CN
-F0-76-1C (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-F0761C (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
F4-28-33 (hex) MMPC Inc.
F42833 (base 16) MMPC Inc.
#F313, KAIST-ICC, 193 Munjiro Yuseong-gu
@@ -2864,12 +2846,6 @@ CC3429 (base 16) TP-LINK TECHNOLOGIES CO.,LTD.
Haidian District BEIJING 100089
CN
-F8-A9-63 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-F8A963 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
48-A2-B7 (hex) Kodofon JSC
48A2B7 (base 16) Kodofon JSC
97 Moskovskyi pr.
@@ -3008,12 +2984,6 @@ B424E7 (base 16) Codetek Technology Co.,Ltd
Salo N.A. 24101
FI
-F0-61-30 (hex) Advantage Pharmacy Services, LLC
-F06130 (base 16) Advantage Pharmacy Services, LLC
- 371A Highland Colony Parkway
- Ridgeland MISSISSIPPI 39157
- US
-
D4-81-CA (hex) iDevices, LLC
D481CA (base 16) iDevices, LLC
136 Simsbury, Rd
@@ -5021,12 +4991,6 @@ E0EF25 (base 16) Lintes Technology Co., Ltd.
New Taipei City 23511
TW
-CC-EE-D9 (hex) VAHLE DETO GmbH
-CCEED9 (base 16) VAHLE DETO GmbH
- Gewerbepark Süd 11
- Kufstein Tirol 6330
- AT
-
64-5E-BE (hex) Yahoo! JAPAN
645EBE (base 16) Yahoo! JAPAN
Midtown Tower
@@ -5363,12 +5327,6 @@ D4206D (base 16) HTC Corporation
College Station Texas 77842
US
-00-B3-38 (hex) Kontron Design Manufacturing Services (M) Sdn. Bhd
-00B338 (base 16) Kontron Design Manufacturing Services (M) Sdn. Bhd
- Plot 554, Lorong Perusahaan 4
- Prai Penang 13600
- MY
-
94-DE-0E (hex) SmartOptics AS
94DE0E (base 16) SmartOptics AS
Stalfjaera 9
@@ -10856,12 +10814,6 @@ A8CE90 (base 16) CVC
Pune Maharashtra 411045
IN
-00-17-F3 (hex) Harris Corparation
-0017F3 (base 16) Harris Corparation
- 1025 West NASA Blvd
- Melbourne FL 32919
- US
-
00-17-F8 (hex) Motech Industries Inc.
0017F8 (base 16) Motech Industries Inc.
6F, No. 248, Sec. 3, Pei-Shen Rd.,
@@ -12974,12 +12926,6 @@ A8CE90 (base 16) CVC
Seoul 137-070
KR
-00-26-54 (hex) 3Com Corporation
-002654 (base 16) 3Com Corporation
- 5353 Betsy Ross Drive
- Santa Clara California 95054-1162
- US
-
00-0F-D0 (hex) ASTRI
000FD0 (base 16) ASTRI
18/F Tower 6, Gateway, 9 Canton Rd
@@ -14354,12 +14300,6 @@ A8CE90 (base 16) CVC
Sunnyvale CA 94089
US
-00-0B-A3 (hex) Siemens AG, I&S
-000BA3 (base 16) Siemens AG, I&S
- Werner-von-Siemens-Straße 65
- Erlangen Bavaria 91052
- DE
-
00-0B-91 (hex) Aglaia Gesellschaft für Bildverarbeitung und Kommunikation mbH
000B91 (base 16) Aglaia Gesellschaft für Bildverarbeitung und Kommunikation mbH
Tiniusstraße 12-15
@@ -14750,12 +14690,6 @@ A8CE90 (base 16) CVC
Taipei Hsien 251
TW
-00-0B-23 (hex) Siemens Subscriber Networks
-000B23 (base 16) Siemens Subscriber Networks
- 4849 Alpha Road
- Dallas Texas 74244
- US
-
00-0A-7A (hex) Kyoritsu Electric Co., Ltd.
000A7A (base 16) Kyoritsu Electric Co., Ltd.
2-3-17
@@ -15452,12 +15386,6 @@ A8CE90 (base 16) CVC
DE
-00-07-3A (hex) Inventel Systemes
-00073A (base 16) Inventel Systemes
- 35, rue Toumefort
-
- FR
-
00-07-34 (hex) ONStor, Inc.
000734 (base 16) ONStor, Inc.
130-B Knowles Drive
@@ -16058,12 +15986,6 @@ A8CE90 (base 16) CVC
Sunnyvale CA 94089
US
-00-04-75 (hex) 3 Com Corporation
-000475 (base 16) 3 Com Corporation
- 5400 Bayfront Plaza
- Santa Clara CA 95052
- US
-
00-04-6F (hex) Digitel S/A Industria Eletronica
00046F (base 16) Digitel S/A Industria Eletronica
R. Doutor Joao Ignacio, 1165
@@ -16661,24 +16583,12 @@ A8CE90 (base 16) CVC
IT
-00-04-AE (hex) Sullair Corporation
-0004AE (base 16) Sullair Corporation
- 3700 East Michigan Blvd
- Michigan City IN 46360
- US
-
00-04-AB (hex) Comverse Network Systems, Inc.
0004AB (base 16) Comverse Network Systems, Inc.
29 Habarzel Street.
IL
-00-04-9F (hex) Freescale Semiconductor
-00049F (base 16) Freescale Semiconductor
- 7700 West Parmer Lane
- Austin TX 78729
- US
-
00-04-A4 (hex) NetEnabled, Inc.
0004A4 (base 16) NetEnabled, Inc.
1275 Kinnear Rd.
@@ -17990,12 +17900,6 @@ A8CE90 (base 16) CVC
PALO ALTO CA 94306-1506
US
-00-90-93 (hex) NANAO CORPORATION
-009093 (base 16) NANAO CORPORATION
- 153 SHIMOKASHIWANO, MATTO
- ISHIKAWA 924-8566
- JP
-
00-90-B4 (hex) WILLOWBROOK TECHNOLOGIES
0090B4 (base 16) WILLOWBROOK TECHNOLOGIES
7120 HAYVENHURST AVE.-STE.#401
@@ -18218,12 +18122,6 @@ A8CE90 (base 16) CVC
GERMANTOWN MD 20874
US
-00-50-04 (hex) 3COM CORPORATION
-005004 (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-50-72 (hex) CORVIS CORPORATION
005072 (base 16) CORVIS CORPORATION
8320 GUILFORD ROAD
@@ -18800,12 +18698,6 @@ A8CE90 (base 16) CVC
33700 MERIGNAC
FR
-00-90-CE (hex) TETRA GmbH
-0090CE (base 16) TETRA GmbH
- GEWERBEPARK AmWald 4
- D-98693 ILMENAU
- DE
-
00-90-E3 (hex) AVEX ELECTRONICS INC.
0090E3 (base 16) AVEX ELECTRONICS INC.
4807 BRADFORD DRIVE
@@ -19778,12 +19670,6 @@ A8CE90 (base 16) CVC
IRVINE CA 92718
US
-00-20-3D (hex) Honeywell ECC
-00203D (base 16) Honeywell ECC
- 1985 Douglas Drive
- Golden Valley MN 55422
- US
-
00-20-19 (hex) OHLER GMBH
002019 (base 16) OHLER GMBH
MAYBACHSTRASE 30
@@ -19922,12 +19808,6 @@ A8CE90 (base 16) CVC
BOCA RATON FL 33487
US
-00-A0-D1 (hex) INVENTEC CORPORATION
-00A0D1 (base 16) INVENTEC CORPORATION
- INVENTEC BUILDING
- TAIWAN TAIWAN R.O.C.
- TW
-
00-A0-AE (hex) NUCOM SYSTEMS, INC.
00A0AE (base 16) NUCOM SYSTEMS, INC.
9F-6, NO 4, LANE
@@ -20126,12 +20006,6 @@ A8CE90 (base 16) CVC
TAIWAN TAIWAN R.O.C.
TW
-00-20-AF (hex) 3COM CORPORATION
-0020AF (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-20-48 (hex) Marconi Communications
002048 (base 16) Marconi Communications
1000 Fore Drive
@@ -21440,24 +21314,6 @@ C4282D (base 16) Embedded Intellect Pty Ltd
CEDEX Paris 75512
FR
-B8-70-F4 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-B870F4 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
-00-0F-B0 (hex) COMPAL ELECTRONICS, INC.
-000FB0 (base 16) COMPAL ELECTRONICS, INC.
- 581 Juikuang Road,Neihu,
- Taipei 114
- TW
-
-1C-75-08 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-1C7508 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
38-29-DD (hex) ONvocal Inc
3829DD (base 16) ONvocal Inc
104 Otis Street, Ste 28
@@ -22322,12 +22178,6 @@ D059E4 (base 16) Samsung Electronics Co.,Ltd
Gumi Gyeongbuk 730-350
KR
-00-0B-3B (hex) devolo AG
-000B3B (base 16) devolo AG
- Sonnenweg 11
- Aachen NRW 52070
- DE
-
00-1D-20 (hex) Comtrend Corporation
001D20 (base 16) Comtrend Corporation
3F-1 10 LANE 609 CHUNG HSIN ROAD, SEC 5, SAN CHUNG CITY, TAIPEI TAIWAN 241
@@ -22970,12 +22820,6 @@ E80959 (base 16) Guoguang Electric Co.,Ltd
67100 L'AQUILA
IT
-00-1E-33 (hex) INVENTEC Corporation
-001E33 (base 16) INVENTEC Corporation
- Inventec Building, 66 Hou-Kang Street
- Taipei 111
- TW
-
00-1A-29 (hex) Johnson Outdoors Marine Electronics d/b/a Minnkota
001A29 (base 16) Johnson Outdoors Marine Electronics d/b/a Minnkota
1220 Old Alpharetta Rd
@@ -23270,24 +23114,6 @@ A09E1A (base 16) Polar Electro Oy
Kempele Oulu 90440
FI
-D0-B2-C4 (hex) Technicolor CH USA Inc.
-D0B2C4 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-FC-94-E3 (hex) Technicolor CH USA Inc.
-FC94E3 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-FC-52-8D (hex) Technicolor CH USA Inc.
-FC528D (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
D8-4A-87 (hex) OI ELECTRIC CO.,LTD
D84A87 (base 16) OI ELECTRIC CO.,LTD
7-3-16 KIKUNA
@@ -25106,12 +24932,6 @@ A4EE57 (base 16) Seiko Epson Corporation
SUWA-SHI NAGANO-KEN 392-8502
JP
-48-00-33 (hex) Technicolor CH USA Inc.
-480033 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
14-B3-1F (hex) Dell Inc.
14B31F (base 16) Dell Inc.
One Dell Way
@@ -25496,12 +25316,6 @@ E8D11B (base 16) ASKEY COMPUTER CORP
Kulim Kedah 09000
MY
-14-98-7D (hex) Technicolor CH USA Inc.
-14987D (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
D4-CF-37 (hex) Symbolic IO
D4CF37 (base 16) Symbolic IO
101 Crawfords Corner Rd.
@@ -25553,9 +25367,6 @@ E048AF (base 16) Premietech Limited
shenzhen Guangdong 518000
CN
-E8-9E-0C (hex) Private
-E89E0C (base 16) Private
-
D8-A1-05 (hex) Syslane, Co., Ltd.
D8A105 (base 16) Syslane, Co., Ltd.
#1201, Megacenter, SKntechno-park,, Sangdaeweon-dong, Joongweon-gu
@@ -26204,12 +26015,6 @@ F46BEF (base 16) Sagemcom Broadband SAS
Qingdao Shandong 266024
CN
-D0-5A-00 (hex) Technicolor CH USA Inc.
-D05A00 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
70-F1-1C (hex) Shenzhen Ogemray Technology Co.,Ltd
70F11C (base 16) Shenzhen Ogemray Technology Co.,Ltd
4/F,5Bldg,Dongwu Industrial Park, Donghuan 1st Rd, Longhua District.
@@ -26408,9 +26213,6 @@ F83441 (base 16) Intel Corporate
Dongguan 523808
CN
-54-4E-45 (hex) Private
-544E45 (base 16) Private
-
DC-EB-53 (hex) Wuhan QianXiao Elecronic Technology CO.,LTD
DCEB53 (base 16) Wuhan QianXiao Elecronic Technology CO.,LTD
Guanggu Xinzhongxin, No.303 of Guanggu road, East lake development zone
@@ -26447,12 +26249,6 @@ B40F3B (base 16) Tenda Technology Co.,Ltd.Dongguan branch
Dongguan Guangdong 523770
CN
-10-62-D0 (hex) Technicolor CH USA Inc.
-1062D0 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
78-02-B1 (hex) Cisco Systems, Inc
7802B1 (base 16) Cisco Systems, Inc
80 West Tasman Drive
@@ -26585,12 +26381,6 @@ A00460 (base 16) NETGEAR
Hong Kong KOWLOON 999077
HK
-11-11-11 (hex) Private
-111111 (base 16) Private
-
-FC-C2-33 (hex) Private
-FCC233 (base 16) Private
-
28-30-AC (hex) Frontiir Co. Ltd.
2830AC (base 16) Frontiir Co. Ltd.
5 Bayint Naung Road, Hlaing Township
@@ -27404,12 +27194,6 @@ D88466 (base 16) Extreme Networks, Inc.
Round Rock TX 78682
US
-3C-9A-77 (hex) Technicolor CH USA Inc.
-3C9A77 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
6C-2A-CB (hex) Paxton Access Ltd
6C2ACB (base 16) Paxton Access Ltd
Paxton House
@@ -28904,12 +28688,6 @@ E4EA83 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT
SHENZHEN GUANGDONG 518105
CN
-D0-8A-91 (hex) Technicolor CH USA Inc.
-D08A91 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
00-15-D0 (hex) ARRIS Group, Inc.
0015D0 (base 16) ARRIS Group, Inc.
6450 Sequence Drive
@@ -29273,6 +29051,18 @@ B0EB57 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
Dongguan 523808
CN
+8C-15-C7 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+8C15C7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+A4-BE-2B (hex) HUAWEI TECHNOLOGIES CO.,LTD
+A4BE2B (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
60-FA-9D (hex) HUAWEI TECHNOLOGIES CO.,LTD
60FA9D (base 16) HUAWEI TECHNOLOGIES CO.,LTD
No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
@@ -29297,105 +29087,99 @@ DC9914 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
Beijing 100053
CN
-8C-15-C7 (hex) HUAWEI TECHNOLOGIES CO.,LTD
-8C15C7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
- No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
- Dongguan 523808
- CN
-
-A4-BE-2B (hex) HUAWEI TECHNOLOGIES CO.,LTD
-A4BE2B (base 16) HUAWEI TECHNOLOGIES CO.,LTD
- No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
- Dongguan 523808
- CN
-
7C-96-D2 (hex) Fihonest communication co.,Ltd
7C96D2 (base 16) Fihonest communication co.,Ltd
The Frist Building ,ShangKeng Industrial Zone, Changping Town
Dongguan Guangdong 523560
CN
-B8-F9-34 (hex) Sony Mobile Communications AB
-B8F934 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
- Shinagawa-ku Tokyo 140-0002
- JP
+90-4C-81 (hex) Hewlett Packard Enterprise
+904C81 (base 16) Hewlett Packard Enterprise
+ 8000 Foothills Blvd.
+ Roseville CA 95747
+ US
-58-17-0C (hex) Sony Mobile Communications AB
-58170C (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
- Shinagawa-ku Tokyo 140-0002
- JP
+8C-35-79 (hex) QDIQO Sp. z o.o.
+8C3579 (base 16) QDIQO Sp. z o.o.
+ Stanisława Wyspiańskiego 11
+ Zielona Góra lubuskie 65-036
+ PL
-6C-23-B9 (hex) Sony Mobile Communications AB
-6C23B9 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
- Shinagawa-ku Tokyo 140-0002
- JP
+34-E1-2D (hex) Intel Corporate
+34E12D (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+8C-81-26 (hex) ARCOM
+8C8126 (base 16) ARCOM
+ ZAC de la Loyère
+ FRAGNES LA LOYERE 71530
+ FR
-24-21-AB (hex) Sony Mobile Communications AB
-2421AB (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+30-39-26 (hex) Sony Mobile Communications Inc
+303926 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-18-13 (hex) Sony Mobile Communications AB
-001813 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+20-54-76 (hex) Sony Mobile Communications Inc
+205476 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-1E-45 (hex) Sony Mobile Communications AB
-001E45 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+B8-F9-34 (hex) Sony Mobile Communications Inc
+B8F934 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-BC-6E-64 (hex) Sony Mobile Communications AB
-BC6E64 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+58-17-0C (hex) Sony Mobile Communications Inc
+58170C (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-EB-2D (hex) Sony Mobile Communications AB
-00EB2D (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+6C-23-B9 (hex) Sony Mobile Communications Inc
+6C23B9 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-30-39-26 (hex) Sony Mobile Communications AB
-303926 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+24-21-AB (hex) Sony Mobile Communications Inc
+2421AB (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-20-54-76 (hex) Sony Mobile Communications AB
-205476 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-18-13 (hex) Sony Mobile Communications Inc
+001813 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-1C-7B-21 (hex) Sony Mobile Communications AB
-1C7B21 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+A0-E4-53 (hex) Sony Mobile Communications Inc
+A0E453 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-A0-E4-53 (hex) Sony Mobile Communications AB
-A0E453 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+BC-6E-64 (hex) Sony Mobile Communications Inc
+BC6E64 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-21-9E (hex) Sony Mobile Communications AB
-00219E (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-EB-2D (hex) Sony Mobile Communications Inc
+00EB2D (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-28-3F-69 (hex) Sony Mobile Communications AB
-283F69 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+1C-7B-21 (hex) Sony Mobile Communications Inc
+1C7B21 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
@@ -29417,6 +29201,24 @@ B8B7F1 (base 16) Wistron Neweb Corporation
Seoul KS013
KR
+A4-53-85 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
+A45385 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
+ Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China
+ Weifang Shandong 261205
+ CN
+
+AC-FD-93 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
+ACFD93 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
+ Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China
+ Weifang Shandong 261205
+ CN
+
+D4-21-22 (hex) Sercomm Corporation.
+D42122 (base 16) Sercomm Corporation.
+ 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
+ Miao-Lih Hsuan 115
+ TW
+
00-13-8A (hex) Qingdao GoerTek Technology Co., Ltd.
00138A (base 16) Qingdao GoerTek Technology Co., Ltd.
Room 605,Innovation Building,Hi-tech Industrial Park,
@@ -29435,23 +29237,23 @@ B8B7F1 (base 16) Wistron Neweb Corporation
Weifang Shandong 261000
CN
-A4-53-85 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
-A45385 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
- Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China
- Weifang Shandong 261205
- CN
+A8-D4-98 (hex) Avira Operations GmbH & Co. KG
+A8D498 (base 16) Avira Operations GmbH & Co. KG
+ Kaplaneiweg 1
+ Tettnang Baden-Wuerttermberg 88069
+ DE
-AC-FD-93 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
-ACFD93 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
- Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China
- Weifang Shandong 261205
- CN
+98-A4-04 (hex) Ericsson AB
+98A404 (base 16) Ericsson AB
+ Torshamnsgatan 36
+ Stockholm SE-164 80
+ SE
-0C-E0-DC (hex) Samsung Electronics Co.,Ltd
-0CE0DC (base 16) Samsung Electronics Co.,Ltd
- #94-1, Imsoo-Dong
- Gumi Gyeongbuk 730-350
- KR
+00-CC-3F (hex) Universal Electronics, Inc.
+00CC3F (base 16) Universal Electronics, Inc.
+ 201 E. Sandpointe Ave
+ Santa Ana CA 92707
+ US
10-8E-E0 (hex) Samsung Electronics Co.,Ltd
108EE0 (base 16) Samsung Electronics Co.,Ltd
@@ -29471,17 +29273,11 @@ ACFD93 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
Gumi Gyeongbuk 730-350
KR
-D4-21-22 (hex) Sercomm Corporation.
-D42122 (base 16) Sercomm Corporation.
- 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
- Miao-Lih Hsuan 115
- TW
-
-F4-EE-14 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
-F4EE14 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
- Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan
- Shenzhen Guangdong 518057
- CN
+0C-E0-DC (hex) Samsung Electronics Co.,Ltd
+0CE0DC (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
6C-59-40 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
6C5940 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
@@ -29495,23 +29291,17 @@ F4EE14 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
Shenzhen Guangdong 518057
CN
-A8-D4-98 (hex) Avira Operations GmbH & Co. KG
-A8D498 (base 16) Avira Operations GmbH & Co. KG
- Kaplaneiweg 1
- Tettnang Baden-Wuerttermberg 88069
- DE
-
-98-A4-04 (hex) Ericsson AB
-98A404 (base 16) Ericsson AB
- Torshamnsgatan 36
- Stockholm SE-164 80
- SE
+F4-EE-14 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+F4EE14 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+ Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan
+ Shenzhen Guangdong 518057
+ CN
-00-CC-3F (hex) Universal Electronics, Inc.
-00CC3F (base 16) Universal Electronics, Inc.
- 201 E. Sandpointe Ave
- Santa Ana CA 92707
- US
+20-A6-0C (hex) Xiaomi Communications Co Ltd
+20A60C (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
50-61-BF (hex) Cisco Systems, Inc
5061BF (base 16) Cisco Systems, Inc
@@ -29519,18 +29309,18 @@ A8D498 (base 16) Avira Operations GmbH & Co. KG
San Jose CA 94568
US
-20-A6-0C (hex) Xiaomi Communications Co Ltd
-20A60C (base 16) Xiaomi Communications Co Ltd
- The Rainbow City of China Resources
- NO.68, Qinghe Middle Street Haidian District, Beijing 100085
- CN
-
04-AB-18 (hex) ELECOM CO.,LTD.
04AB18 (base 16) ELECOM CO.,LTD.
11F Tokyubancho Bldg. 6-2,
Chiyoda-ku Tokyo 102-0081
JP
+4C-5E-0C (hex) Routerboard.com
+4C5E0C (base 16) Routerboard.com
+ Mikrotikls SIA
+ Riga LV1009
+ LV
+
00-26-BD (hex) JTEC Card &amp; Communication Co., Ltd
0026BD (base 16) JTEC Card &amp; Communication Co., Ltd
Dabo Bldg, 4F, 61-1, Gyesu-dong, Sosa-gu
@@ -29543,12 +29333,6 @@ A8D498 (base 16) Avira Operations GmbH & Co. KG
CH-8401 Winterthur
CH
-4C-5E-0C (hex) Routerboard.com
-4C5E0C (base 16) Routerboard.com
- Mikrotikls SIA
- Riga LV1009
- LV
-
64-1C-67 (hex) DIGIBRAS INDUSTRIA DO BRASILS/A
641C67 (base 16) DIGIBRAS INDUSTRIA DO BRASILS/A
Rua Tambaqui, 180-B - MANAUS - AM ¨C BRAZIL
@@ -29561,6 +29345,732 @@ A8D498 (base 16) Avira Operations GmbH & Co. KG
Stafford ST16 1TW
GB
+FC-94-E3 (hex) Technicolor CH USA Inc.
+FC94E3 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+D0-B2-C4 (hex) Technicolor CH USA Inc.
+D0B2C4 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+48-00-33 (hex) Technicolor CH USA Inc.
+480033 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+14-98-7D (hex) Technicolor CH USA Inc.
+14987D (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+D0-5A-00 (hex) Technicolor CH USA Inc.
+D05A00 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+10-62-D0 (hex) Technicolor CH USA Inc.
+1062D0 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+3C-9A-77 (hex) Technicolor CH USA Inc.
+3C9A77 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+D0-8A-91 (hex) Technicolor CH USA Inc.
+D08A91 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+FC-52-8D (hex) Technicolor CH USA Inc.
+FC528D (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+40-C3-C6 (hex) SnapRoute
+40C3C6 (base 16) SnapRoute
+ 3960 Freedom Circle, Suite 100
+ Santa Clara CA 95054
+ US
+
+E8-9E-0C (hex) Private
+E89E0C (base 16) Private
+
+54-4E-45 (hex) Private
+544E45 (base 16) Private
+
+00-90-CE (hex) avateramedical Mechatronics GmbH
+0090CE (base 16) avateramedical Mechatronics GmbH
+ Gewerbepark „Am Wald“ 4
+ ILMENAU D-98693
+ DE
+
+30-0E-E3 (hex) Aquantia Corporation
+300EE3 (base 16) Aquantia Corporation
+ 700 Tasman Drive
+ Milpitas CA 95035
+ US
+
+74-87-BB (hex) Ciena Corporation
+7487BB (base 16) Ciena Corporation
+ 7035 Ridge Road
+ Hanover MD 21076
+ US
+
+EC-38-73 (hex) Juniper Networks
+EC3873 (base 16) Juniper Networks
+ 1133 Innovation Way
+ Sunnyvale CA 94089
+ US
+
+00-1E-45 (hex) Sony Mobile Communications Inc
+001E45 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
+ Shinagawa-ku Tokyo 140-0002
+ JP
+
+00-21-9E (hex) Sony Mobile Communications Inc
+00219E (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
+ Shinagawa-ku Tokyo 140-0002
+ JP
+
+28-3F-69 (hex) Sony Mobile Communications Inc
+283F69 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
+ Shinagawa-ku Tokyo 140-0002
+ JP
+
+E8-C5-7A (hex) Ufispace Co., LTD.
+E8C57A (base 16) Ufispace Co., LTD.
+ 9F., No. 81 Jhongcheng Rd., Tucheng Dist.,
+ New Taipei 23674
+ TW
+
+C4-B8-B4 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+C4B8B4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+F8-99-10 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
+F89910 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
+ Phase 3, Bayan Lepas FIZ
+ Bayan Lepas Penang 11900
+ MY
+
+50-E0-EF (hex) Nokia
+50E0EF (base 16) Nokia
+ 600 March Road
+ Kanata Ontario K2K 2E6
+ CA
+
+11-11-11 (hex) Private
+111111 (base 16) Private
+
+2C-18-75 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd
+2C1875 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd
+ 7F,Block A,Skyworth Building,
+ Shenzhen Guangdong 518057
+ CN
+
+28-9E-FC (hex) Sagemcom Broadband SAS
+289EFC (base 16) Sagemcom Broadband SAS
+ 250, route de l'Empereur
+ Rueil Malmaison Cedex hauts de seine 92848
+ FR
+
+84-C9-C6 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT
+84C9C6 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT
+ SONGGANG
+ SHENZHEN GUANGDONG 518105
+ CN
+
+20-16-3D (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
+20163D (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
+ Phase 3, Bayan Lepas FIZ
+ Bayan Lepas Penang 11900
+ MY
+
+70-2A-D5 (hex) Samsung Electronics Co.,Ltd
+702AD5 (base 16) Samsung Electronics Co.,Ltd
+ 129, Samsung-ro, Youngtongl-Gu
+ Suwon Gyeonggi-Do 16677
+ KR
+
+68-DD-26 (hex) Shanghai Focus Vision Security Technology Co.,Ltd
+68DD26 (base 16) Shanghai Focus Vision Security Technology Co.,Ltd
+ No.4888 Hunan Rd, Pudong New District
+ Shanghai Shanghai 201317
+ CN
+
+D8-91-2A (hex) Zyxel Communications Corporation
+D8912A (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+8C-B0-E9 (hex) Samsung Electronics.,LTD
+8CB0E9 (base 16) Samsung Electronics.,LTD
+ 129, Samsung-ro, Yeongtong-gu
+ Suwon Gyeonggi-Do 443-742
+ KR
+
+00-0B-A3 (hex) Siemens AG
+000BA3 (base 16) Siemens AG
+ Werner-von-Siemens-Straße 65
+ Erlangen Bavaria 91052
+ DE
+
+00-0B-23 (hex) Siemens Home & Office Comm. Devices
+000B23 (base 16) Siemens Home & Office Comm. Devices
+ 4849 Alpha Road
+ Dallas Texas 74244
+ US
+
+C4-FE-E2 (hex) AMICCOM Electronics Corporation
+C4FEE2 (base 16) AMICCOM Electronics Corporation
+ 10F, No.18, Taiyuan St., Zhubei City
+ Hsinchu Country Taiwan 30265
+ TW
+
+B4-4B-D6 (hex) IEEE Registration Authority
+B44BD6 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+48-68-34 (hex) Silicon Motion, Inc.
+486834 (base 16) Silicon Motion, Inc.
+ 8F, No. 36, Taiyuan St.
+ Zhubei City Hsinchu County 30265
+ TW
+
+EC-58-EA (hex) Ruckus Wireless
+EC58EA (base 16) Ruckus Wireless
+ 350 West Java Drive
+ Sunnyvale CA 94089
+ US
+
+74-59-33 (hex) Danal Entertainment
+745933 (base 16) Danal Entertainment
+ 9th Fl. Bundang First Tower, 55 Bundang-ro, Bundang-gu
+ Seongnam-si Gyeonggi-do 13591
+ KR
+
+00-9D-6B (hex) Murata Manufacturing Co., Ltd.
+009D6B (base 16) Murata Manufacturing Co., Ltd.
+ 1-10-1, Higashikotari
+ Nagaokakyo-shi Kyoto 617-8555
+ JP
+
+B0-B8-67 (hex) Hewlett Packard Enterprise
+B0B867 (base 16) Hewlett Packard Enterprise
+ 8000 Foothills Blvd.
+ Roseville CA 95747
+ US
+
+20-F7-7C (hex) vivo Mobile Communication Co., Ltd.
+20F77C (base 16) vivo Mobile Communication Co., Ltd.
+ #283,BBK Road
+ Wusha,Chang'An DongGuan City,Guangdong, 523860
+ CN
+
+00-04-AE (hex) Sullair Corporation
+0004AE (base 16) Sullair Corporation
+ 3700 East Michigan Blvd
+ Michigan City IN 46360
+ US
+
+F0-61-30 (hex) Advantage Pharmacy Services, LLC
+F06130 (base 16) Advantage Pharmacy Services, LLC
+ PO Box 7
+ Madison MO 39130-0007
+ US
+
+FC-B1-0D (hex) Shenzhen Tian Kun Technology Co.,LTD.
+FCB10D (base 16) Shenzhen Tian Kun Technology Co.,LTD.
+ Layer 8,Nanyuan Maple Building,No.1088 Nanshan Avenue,Nanshan Street,Nanshan District,Shenzhen
+ Shenzhen Guangdong 518048
+ CN
+
+F8-A9-63 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+F8A963 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+B8-70-F4 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+B870F4 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+1C-75-08 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+1C7508 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+F0-76-1C (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+F0761C (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+88-DF-9E (hex) New H3C Technologies Co., Ltd
+88DF9E (base 16) New H3C Technologies Co., Ltd
+ 466 Changhe Road, Binjiang District
+ Hangzhou Zhejiang 310052
+ CN
+
+2C-7C-E4 (hex) Wuhan Tianyu Information Industry Co., Ltd.
+2C7CE4 (base 16) Wuhan Tianyu Information Industry Co., Ltd.
+ HUST Industry Park, East-Lake Development Zone
+ Wuhan Hubei 430223
+ CN
+
+34-27-92 (hex) FREEBOX SAS
+342792 (base 16) FREEBOX SAS
+ 16 rue de la Ville l'Eveque
+ PARIS IdF 75008
+ FR
+
+EC-6F-0B (hex) FADU, Inc.
+EC6F0B (base 16) FADU, Inc.
+ 4th FL, 8, Bongeunsa-ro 68-gil, Gangnam-gu
+ Seoul 06153
+ KR
+
+10-62-E5 (hex) Hewlett Packard
+1062E5 (base 16) Hewlett Packard
+ 11445 Compaq Center Drive
+ Houston TX 77070
+ US
+
+00-17-F3 (hex) Harris Corporation
+0017F3 (base 16) Harris Corporation
+ 1025 West NASA Blvd
+ Melbourne FL 32919
+ US
+
+3C-71-BF (hex) Espressif Inc.
+3C71BF (base 16) Espressif Inc.
+ Room 204, Building 2, 690 Bibo Road, Pudong New Area
+ Shanghai Shanghai 201203
+ CN
+
+14-D1-69 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+14D169 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+BC-E2-65 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+BCE265 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+D0-16-B4 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+D016B4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+00-B3-38 (hex) Kontron Asia Pacific Design Sdn. Bhd
+00B338 (base 16) Kontron Asia Pacific Design Sdn. Bhd
+ Plot 554, Lorong Perusahaan 4
+ Prai Free Trade Zone Prai, Penang 13600
+ MY
+
+00-B6-70 (hex) Cisco Systems, Inc
+00B670 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+50-DC-FC (hex) ECOCOM
+50DCFC (base 16) ECOCOM
+ 15ST,Block A,Fortune Plaza, No.7002 ShenNan Avenue, Futian District
+ Shenzhen Guangdong 518040
+ CN
+
+C0-83-59 (hex) IEEE Registration Authority
+C08359 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+24-4C-E3 (hex) Amazon Technologies Inc.
+244CE3 (base 16) Amazon Technologies Inc.
+ P.O Box 8102
+ Reno 89507
+ US
+
+48-98-CA (hex) Sichuan AI-Link Technology Co., Ltd.
+4898CA (base 16) Sichuan AI-Link Technology Co., Ltd.
+ Anzhou,Industrial Park
+ Anzhou,Industrial Park Sichuan 621000
+ CN
+
+20-E8-82 (hex) zte corporation
+20E882 (base 16) zte corporation
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
+ shenzhen guangdong 518057
+ CN
+
+00-04-9F (hex) Freescale Semiconductor
+00049F (base 16) Freescale Semiconductor
+ 2100 East Elliot
+ Tempe AZ 85284
+ US
+
+00-0F-B0 (hex) Compal Electronics INC.
+000FB0 (base 16) Compal Electronics INC.
+ No.8 , Nandong Road , PingZhen Dist.
+ Taoyuan Taiwan 32455
+ TW
+
+98-8E-D4 (hex) ITEL MOBILE LIMITED
+988ED4 (base 16) ITEL MOBILE LIMITED
+ RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K
+ Hong Kong KOWLOON 999077
+ HK
+
+A4-56-CC (hex) Technicolor CH USA Inc.
+A456CC (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+00-0B-3B (hex) devolo AG
+000B3B (base 16) devolo AG
+ Charlottenburger Allee 67
+ Aachen NRW 52068
+ DE
+
+88-9F-6F (hex) Samsung Electronics Co.,Ltd
+889F6F (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+9C-F6-DD (hex) IEEE Registration Authority
+9CF6DD (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+00-90-93 (hex) EIZO Corporation
+009093 (base 16) EIZO Corporation
+ 153 Shimokashiwano
+ Hakusan Ishikawa 924-8856
+ JP
+
+E0-49-ED (hex) Audeze LLC
+E049ED (base 16) Audeze LLC
+ 3410 S Susan st
+ Santa Ana CA 92704
+ US
+
+40-62-EA (hex) China Mobile Group Device Co.,Ltd.
+4062EA (base 16) China Mobile Group Device Co.,Ltd.
+ 32 Xuanwumen West Street,Xicheng District
+ Beijing 100053
+ CN
+
+2C-15-E1 (hex) Phicomm (Shanghai) Co., Ltd.
+2C15E1 (base 16) Phicomm (Shanghai) Co., Ltd.
+ 3666 SiXian Rd.,Songjiang District
+ Shanghai Shanghai 201616
+ CN
+
+14-E9-B2 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+14E9B2 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+D4-74-1B (hex) Beijing HuaDa ZhiBao Electronic System Co.,Ltd.
+D4741B (base 16) Beijing HuaDa ZhiBao Electronic System Co.,Ltd.
+ No.1 Gaojiayuan,Chaoyang District,Beijing,China
+ Beijing Beijing 100015
+ CN
+
+B4-DD-D0 (hex) Continental Automotive Hungary Kft
+B4DDD0 (base 16) Continental Automotive Hungary Kft
+ Napmátka u. 6.
+ Budapest Pest H-1106
+ HU
+
+A4-35-23 (hex) Guangdong Donyan Network Technologies Co.,Ltd.
+A43523 (base 16) Guangdong Donyan Network Technologies Co.,Ltd.
+ No.6,Kejizhong Road,Chuangye Building,Hi-tech Zone
+ Shantou Guangdong 515000
+ CN
+
+30-09-F9 (hex) IEEE Registration Authority
+3009F9 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+04-40-A9 (hex) New H3C Technologies Co., Ltd
+0440A9 (base 16) New H3C Technologies Co., Ltd
+ 466 Changhe Road, Binjiang District
+ Hangzhou Zhejiang 310052
+ CN
+
+DC-39-79 (hex) Cisco Systems, Inc
+DC3979 (base 16) Cisco Systems, Inc
+ 280 Hope Street
+ Mountain View CA 94041
+ US
+
+00-20-3D (hex) Honeywell Environmental & Combustion Controls
+00203D (base 16) Honeywell Environmental & Combustion Controls
+ 1985 Douglas Drive
+ Golden Valley MN 55422
+ US
+
+80-B6-24 (hex) IVS
+80B624 (base 16) IVS
+ 807-809 , Woorim E-biz center, 35, Gwangnaru-ro 6-gil
+ Seoul Seongdong-gu 04799
+ KR
+
+DC-F5-05 (hex) AzureWave Technology Inc.
+DCF505 (base 16) AzureWave Technology Inc.
+ 8F., No. 94, Baozhong Rd.
+ New Taipei City Taiwan 231
+ TW
+
+FC-C2-33 (hex) Private
+FCC233 (base 16) Private
+
+0C-B5-27 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+0CB527 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+84-89-EC (hex) IEEE Registration Authority
+8489EC (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+5C-FB-7C (hex) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd
+5CFB7C (base 16) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd
+ 3/F,A5 Building Zhiyuan Community No.1001,Xueyuan Road Nanshan District
+ Shenzhen Guangdong 518055
+ CN
+
+CC-EE-D9 (hex) VAHLE Automation GmbH
+CCEED9 (base 16) VAHLE Automation GmbH
+ Egerbach 12a
+ Kufstein Schwoich Tirol 6334
+ AT
+
+C8-C2-F5 (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
+C8C2F5 (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
+ Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC
+ Zhuhai Guangdong 519180
+ CN
+
+04-15-D9 (hex) Viwone
+0415D9 (base 16) Viwone
+ 54 - 56 , Avenue Hoche
+ Paris 75008
+ FR
+
+00-20-AF (hex) 3COM
+0020AF (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-04-75 (hex) 3COM
+000475 (base 16) 3COM
+ 5400 Bayfront Plaza
+ Santa Clara CA 95052
+ US
+
+00-07-3A (hex) INVENTEL
+00073A (base 16) INVENTEL
+ 35, rue Toumefort
+
+ FR
+
+00-A0-D1 (hex) INVENTEC CORPORATION
+00A0D1 (base 16) INVENTEC CORPORATION
+ INVENTEC BUILDING
+ TAIWAN TAIWAN R.O.C.
+ TW
+
+00-1E-33 (hex) INVENTEC CORPORATION
+001E33 (base 16) INVENTEC CORPORATION
+ Inventec Building, 66 Hou-Kang Street
+ Taipei 111
+ TW
+
+00-26-54 (hex) 3COM
+002654 (base 16) 3COM
+ 5353 Betsy Ross Drive
+ Santa Clara California 95054-1162
+ US
+
+00-50-04 (hex) 3COM
+005004 (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+CC-C5-E5 (hex) Dell Inc.
+CCC5E5 (base 16) Dell Inc.
+ One Dell Way
+ Round Rock TX 78682
+ US
+
+10-A2-4E (hex) GOLD3LINK ELECTRONICS CO., LTD
+10A24E (base 16) GOLD3LINK ELECTRONICS CO., LTD
+ No.90,Sec.1,Com Lin Rd,Taipei 114,Taiwan,R.O.C
+ Taipei Taiwan 114
+ TW
+
+E8-6A-64 (hex) LCFC(HeFei) Electronics Technology co., ltd
+E86A64 (base 16) LCFC(HeFei) Electronics Technology co., ltd
+ YunGu Road 3188-1
+ Hefei Anhui 230000
+ CN
+
+0C-2A-86 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+0C2A86 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+04-09-A5 (hex) HFR, Inc.
+0409A5 (base 16) HFR, Inc.
+ 5F, Hana EZ Tower
+ Sungnam-si Kyunggi-do 463-870
+ KR
+
+D8-7D-7F (hex) Sagemcom Broadband SAS
+D87D7F (base 16) Sagemcom Broadband SAS
+ 250, route de l'Empereur
+ Rueil Malmaison Cedex hauts de seine 92848
+ FR
+
+A4-ED-43 (hex) IEEE Registration Authority
+A4ED43 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+48-5F-99 (hex) Cloud Network Technology (Samoa) Limited
+485F99 (base 16) Cloud Network Technology (Samoa) Limited
+ Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District
+ Chongqing Chongqing 401332
+ CN
+
+C0-40-04 (hex) Medicaroid Corporation
+C04004 (base 16) Medicaroid Corporation
+ 1-6-4, Minatojima-minamimachi, Chuo-ku
+ Kobe 650-0047
+ JP
+
+8C-61-A3 (hex) ARRIS Group, Inc.
+8C61A3 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+70-4F-B8 (hex) ARRIS Group, Inc.
+704FB8 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+7C-69-6B (hex) Atmosic Technologies
+7C696B (base 16) Atmosic Technologies
+ 12930 Saratoga Ave, Suite B6
+ Saratoga CA 95070
+ US
+
+78-05-5F (hex) Shenzhen WYC Technology Co., Ltd.
+78055F (base 16) Shenzhen WYC Technology Co., Ltd.
+ No.618 Wenzhengxin Building,Hi-tech Park,Nanshan District
+ Shenzhen Guangdong 518000
+ CN
+
+E0-63-DA (hex) Ubiquiti Networks Inc.
+E063DA (base 16) Ubiquiti Networks Inc.
+ 2580 Orchard Pkwy
+ San Jose CA 95131
+ US
+
+50-57-9C (hex) Seiko Epson Corporation
+50579C (base 16) Seiko Epson Corporation
+ 2070 Kotobuki Koaka
+ Matsumoto-shi Nagano-ken 399-8702
+ JP
+
+C8-D9-D2 (hex) Hewlett Packard
+C8D9D2 (base 16) Hewlett Packard
+ 11445 Compaq Center Drive
+ Houston TX 77070
+ US
+
+54-27-8D (hex) NXP (China) Management Ltd.
+54278D (base 16) NXP (China) Management Ltd.
+ 21F, BM InterContinental Business Center, 100 Yu Tong Road
+ Shanghai Shanghai 200070
+ CN
+
+DC-41-E5 (hex) Shenzhen Zhixin Data Service Co., Ltd.
+DC41E5 (base 16) Shenzhen Zhixin Data Service Co., Ltd.
+ Baoyuan Road F518 Fashion Creative Park F3 Blg208
+ Baoan District, Shenzhen Guangdong 518101
+ CN
+
+B0-BE-76 (hex) TP-LINK TECHNOLOGIES CO.,LTD.
+B0BE76 (base 16) TP-LINK TECHNOLOGIES CO.,LTD.
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan
+ Shenzhen Guangdong 518057
+ CN
+
+D8-0D-17 (hex) TP-LINK TECHNOLOGIES CO.,LTD.
+D80D17 (base 16) TP-LINK TECHNOLOGIES CO.,LTD.
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan
+ Shenzhen Guangdong 518057
+ CN
+
+CC-08-FB (hex) TP-LINK TECHNOLOGIES CO.,LTD.
+CC08FB (base 16) TP-LINK TECHNOLOGIES CO.,LTD.
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan
+ Shenzhen Guangdong 518057
+ CN
+
+54-10-31 (hex) SMARTO
+541031 (base 16) SMARTO
+ 25 QUAI GALLIENI
+ SURESNES HAUT DE SEINE 92150
+ FR
+
0C-6F-9C (hex) Shaw Communications Inc.
0C6F9C (base 16) Shaw Communications Inc.
Suite 900, 630 3rd Avenue S.W.
@@ -33857,12 +34367,6 @@ B86091 (base 16) Onnet Technologies and Innovations LLC
Ajman Ajman 52141
AE
-20-1A-06 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-201A06 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
D4-CA-6E (hex) u-blox AG
D4CA6E (base 16) u-blox AG
Zuercherstrasse 68
@@ -35045,12 +35549,6 @@ C02973 (base 16) Audyssey Laboratories Inc.
Los Angeles CA 90079
US
-30-16-8D (hex) ProLon
-30168D (base 16) ProLon
- 1989 Michelin
- Laval Quebec H7L5B7
- CA
-
B4-51-F9 (hex) NB Software
B451F9 (base 16) NB Software
Eichhalde 3
@@ -35573,12 +36071,6 @@ F081AF (base 16) IRZ AUTOMATION TECHNOLOGIES LTD
Seoul 150-871
KR
-AC-86-74 (hex) Open Mesh, Inc.
-AC8674 (base 16) Open Mesh, Inc.
- 5837 NW Skyline Blvd
- Portland OR 97229
- US
-
14-A9-E3 (hex) MST CORPORATION
14A9E3 (base 16) MST CORPORATION
4th Floor Lawford House
@@ -39824,12 +40316,6 @@ D0D286 (base 16) Beckman Coulter K.K.
HAYES Middlesex UB3 3BA
GB
-00-1B-6E (hex) Anue Systems, Inc.
-001B6E (base 16) Anue Systems, Inc.
- 9111 Jollyville Road
- Austin TX 78759
- US
-
00-1B-67 (hex) Cisco Systems Inc
001B67 (base 16) Cisco Systems Inc
The Stella Building
@@ -40598,12 +41084,6 @@ D0D286 (base 16) Beckman Coulter K.K.
Seoul 152-050
KR
-00-1A-31 (hex) SCAN COIN Industries AB
-001A31 (base 16) SCAN COIN Industries AB
- Jagershillgatan 26
- Malmö Skåne 21375
- SE
-
00-1A-38 (hex) Sanmina-SCI
001A38 (base 16) Sanmina-SCI
13000 South Memorial Parkway
@@ -44651,12 +45131,6 @@ D0D286 (base 16) Beckman Coulter K.K.
Praha 5 15000
CZ
-00-0A-5E (hex) 3COM Corporation
-000A5E (base 16) 3COM Corporation
- 5400 Bayfront Plaza
- Santa Clara CA 95052-8145
- US
-
00-0A-52 (hex) AsiaRF Ltd.
000A52 (base 16) AsiaRF Ltd.
3F, No.176, Yongzhen Road
@@ -45077,12 +45551,6 @@ D0D286 (base 16) Beckman Coulter K.K.
DE
-02-60-8C (hex) 3COM CORPORATION
-02608C (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-07-D0 (hex) Automat Engenharia de Automação Ltda.
0007D0 (base 16) Automat Engenharia de Automação Ltda.
Rua Santo Antonio, 917 - Reboucas
@@ -45713,12 +46181,6 @@ D0D286 (base 16) Beckman Coulter K.K.
San Jose CA 95131
US
-00-06-8C (hex) 3COM CORPORATION
-00068C (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-06-85 (hex) NetNearU Corporation
000685 (base 16) NetNearU Corporation
2908 Finfeather Road
@@ -46769,12 +47231,6 @@ D0D286 (base 16) Beckman Coulter K.K.
Santa Clara CA 95054
US
-00-01-03 (hex) 3COM CORPORATION
-000103 (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-06-2B (hex) INTRASERVER TECHNOLOGY
00062B (base 16) INTRASERVER TECHNOLOGY
SEVEN OCTOBER HILL RD.
@@ -46937,12 +47393,6 @@ D0D286 (base 16) Beckman Coulter K.K.
Lulea 97125
SE
-00-30-1E (hex) 3COM EUROPE LTD.
-00301E (base 16) 3COM EUROPE LTD.
- BOUNDARY WAY
- UNITED KINGDOM
- GB
-
00-30-4D (hex) ESI
00304D (base 16) ESI
3701 E. Plano Parkway
@@ -47153,12 +47603,6 @@ D0D286 (base 16) Beckman Coulter K.K.
FUZHOU FUJIAN, CHINA 350002
CN
-00-D0-96 (hex) 3COM EUROPE LTD.
-00D096 (base 16) 3COM EUROPE LTD.
- BOUNDARY WAY
- UNITED KINGDOM
- GB
-
00-D0-03 (hex) COMDA ENTERPRISES CORP.
00D003 (base 16) COMDA ENTERPRISES CORP.
2F, NO. 501-18, CHUNGCHEN ROAD
@@ -48053,12 +48497,6 @@ D0D286 (base 16) Beckman Coulter K.K.
SAN JOSE CA 95119
US
-00-50-99 (hex) 3COM EUROPE, LTD.
-005099 (base 16) 3COM EUROPE, LTD.
- BOUNDARY WAY
- HERTS. HP2 7YU
- GB
-
00-50-A4 (hex) IO TECH, INC.
0050A4 (base 16) IO TECH, INC.
25971 CANNON ROAD
@@ -48173,12 +48611,6 @@ D0D286 (base 16) Beckman Coulter K.K.
Kangdong-Gu Seoul 134-050
KR
-00-90-04 (hex) 3COM EUROPE LTD.
-009004 (base 16) 3COM EUROPE LTD.
- 3COM CENTRE, BOUNDARY WAY
- HERTS. HP2 7YU
- GB
-
00-90-E1 (hex) TELENA S.P.A.
0090E1 (base 16) TELENA S.P.A.
VIA SAVONA, 146
@@ -50099,12 +50531,6 @@ D0D286 (base 16) Beckman Coulter K.K.
VIENNA VA 22182-3964
US
-00-40-84 (hex) HONEYWELL ACS
-004084 (base 16) HONEYWELL ACS
-
- Fort Washington PA 19034
- US
-
00-40-B8 (hex) IDEA ASSOCIATES
0040B8 (base 16) IDEA ASSOCIATES
29 DUNHAM ROAD
@@ -50699,12 +51125,6 @@ D0D286 (base 16) Beckman Coulter K.K.
FT. LAUDERDALE FL 33310-9148
US
-08-00-4E (hex) 3COM EUROPE LTD.
-08004E (base 16) 3COM EUROPE LTD.
- 3COM CENTRE
- UNITED KINGDOM
- GB
-
08-00-4A (hex) BANYAN SYSTEMS INC.
08004A (base 16) BANYAN SYSTEMS INC.
135 FLANDERS ROAD
@@ -51020,42 +51440,6 @@ C05627 (base 16) Belkin International Inc.
RUEIL MALMAISON CEDEX Hauts de Seine 92848
FR
-B8-88-E3 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-B888E3 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone,, Jiangsu,
- KUNSHAN SUZHOU 215300
- CN
-
-00-26-22 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-002622 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
-00-1E-EC (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-001EEC (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 25, THE 3RD Street
- KUNSHAN CITY SUZHOU PROVINCE 215300
- CN
-
-DC-0E-A1 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-DC0EA1 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone,, Jiangsu,
- KUNSHAN SUZHOU 215300
- CN
-
-FC-45-96 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-FC4596 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZON
- KUNSHAN SUZHOU 215300
- CN
-
-20-89-84 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-208984 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone
- KUNSHAN SUZHOU 215300
- CN
-
24-7C-4C (hex) Herman Miller
247C4C (base 16) Herman Miller
Unit 2, 2/F The Factory, 1 Yip Fat Street
@@ -52508,12 +52892,6 @@ AC620D (base 16) Jabil Circuit(Wuxi) Co.,Ltd
Wuxi City Jiangsu 214028
CN
-00-8C-FA (hex) INVENTEC Corporation
-008CFA (base 16) INVENTEC Corporation
- No. 255, Jen-Ho Road Sec. 2, 33547,
- Tachi Taoyuan 33547
- TW
-
00-08-B9 (hex) Kaonmedia CO., LTD.
0008B9 (base 16) Kaonmedia CO., LTD.
#113 Imae 1-Dong, Bundang-Gu
@@ -52901,30 +53279,12 @@ A020A6 (base 16) Espressif Inc.
Shanghai Shanghai 201203
CN
-88-F7-C7 (hex) Technicolor CH USA Inc.
-88F7C7 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-08-95-2A (hex) Technicolor CH USA Inc.
-08952A (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
C4-BB-4C (hex) Zebra Information Tech Co. Ltd
C4BB4C (base 16) Zebra Information Tech Co. Ltd
Room 415, No.569 Anchi Road, JiaDing District
Shanghai 201804
CN
-8C-04-FF (hex) Technicolor CH USA Inc.
-8C04FF (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
00-19-72 (hex) Plexus (Xiamen) Co.,ltd.
001972 (base 16) Plexus (Xiamen) Co.,ltd.
No.6 Xiangxing 2 Road
@@ -53327,18 +53687,6 @@ C411E0 (base 16) Bull Group Co., Ltd
Beijing 100191
CN
-FC-91-14 (hex) Technicolor CH USA Inc.
-FC9114 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-1C-25-E1 (hex) China Mobile IOT Company Limited
-1C25E1 (base 16) China Mobile IOT Company Limited
- NO.8 Yu Ma Road, NanAn Area Chongqing,China
- Chongqing Chongqing 401336
- CN
-
C0-F6-36 (hex) Hangzhou Kuaiyue Technologies, Ltd.
C0F636 (base 16) Hangzhou Kuaiyue Technologies, Ltd.
Dongguan Hitech Park, Building 1-805, 288 Qiuyi Rd, Bingjiang District
@@ -54455,12 +54803,6 @@ D842E2 (base 16) Canary Connect, Inc.
New York 10017
US
-50-09-59 (hex) Technicolor CH USA Inc.
-500959 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
14-33-65 (hex) TEM Mobile Limited
143365 (base 16) TEM Mobile Limited
RM1703, North Block, Cangsong Building, Tairan 6 road, Futian District, Shenzhen.
@@ -56081,12 +56423,6 @@ B04089 (base 16) Senient Systems LTD
Dordrecht Zuid-Holland 3311 AL
NL
-14-B7-F8 (hex) Technicolor CH USA Inc.
-14B7F8 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
F0-6E-32 (hex) MICROTEL INNOVATION S.R.L.
F06E32 (base 16) MICROTEL INNOVATION S.R.L.
Via Armentera 8
@@ -56417,12 +56753,6 @@ E8E732 (base 16) Alcatel-Lucent Enterprise
Mountain View CA 94043
US
-B4-2A-0E (hex) Technicolor CH USA Inc.
-B42A0E (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
E8-DE-8E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
E8DE8E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
Phase 3, Bayan Lepas FIZ
@@ -57041,9 +57371,6 @@ B05508 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
Suwon Gyeonggi-Do 16677
KR
-AC-DE-48 (hex) Private
-ACDE48 (base 16) Private
-
D0-94-66 (hex) Dell Inc.
D09466 (base 16) Dell Inc.
One Dell Way
@@ -58790,12 +59117,6 @@ B4E01D (base 16) CONCEPTION ELECTRONIQUE
Shenzhen Guangdong 518000
CN
-9C-7F-57 (hex) DERA Co. Ltd
-9C7F57 (base 16) DERA Co. Ltd
- Huilongguan Dongdajie No.338, Building A Room 506, Changping District
- Beijing 102208
- CN
-
00-E0-09 (hex) Stratus Technologies
00E009 (base 16) Stratus Technologies
5 Mill and Main Place, Suite 500
@@ -58886,12 +59207,6 @@ E0BAB4 (base 16) Arrcus, Inc
Wuhan Hubei 430074
CN
-CC-3A-DF (hex) Private
-CC3ADF (base 16) Private
-
-60-4B-AA (hex) Private
-604BAA (base 16) Private
-
2C-58-4F (hex) ARRIS Group, Inc.
2C584F (base 16) ARRIS Group, Inc.
6450 Sequence Drive
@@ -58964,29 +59279,29 @@ D8F3DB (base 16) Post CH AG
Framingham MA 01701-9168
US
-3C-F4-F9 (hex) Moda-InnoChips
-3CF4F9 (base 16) Moda-InnoChips
- 42-7(Wonsi-Dong),Dongsan-ro 27beon-gil,Danwon-gu
- Ansan-si Gyeonggi-Do 15433
- KR
-
30-88-41 (hex) Sichuan AI-Link Technology Co., Ltd.
308841 (base 16) Sichuan AI-Link Technology Co., Ltd.
Anzhou,Industrial Park
Anzhou,Industrial Park Sichuan 621000
CN
+80-50-F6 (hex) ITEL MOBILE LIMITED
+8050F6 (base 16) ITEL MOBILE LIMITED
+ RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K
+ Hong Kong KOWLOON 999077
+ HK
+
0C-01-DB (hex) Infinix mobility limited
0C01DB (base 16) Infinix mobility limited
RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG
HongKong HongKong 999077
HK
-80-50-F6 (hex) ITEL MOBILE LIMITED
-8050F6 (base 16) ITEL MOBILE LIMITED
- RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K
- Hong Kong KOWLOON 999077
- HK
+3C-F4-F9 (hex) Moda-InnoChips
+3CF4F9 (base 16) Moda-InnoChips
+ 42-7(Wonsi-Dong),Dongsan-ro 27beon-gil,Danwon-gu
+ Ansan-si Gyeonggi-Do 15433
+ KR
40-1B-5F (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
401B5F (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
@@ -59042,12 +59357,6 @@ A82BB9 (base 16) Samsung Electronics Co.,Ltd
Waterloo ON N2L 5R9
CA
-00-90-7F (hex) Watchguard Technologies, Inc.
-00907F (base 16) Watchguard Technologies, Inc.
- 505 Fifth Ave South
- Seattle WA 98104
- US
-
14-57-9F (hex) HUAWEI TECHNOLOGIES CO.,LTD
14579F (base 16) HUAWEI TECHNOLOGIES CO.,LTD
No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
@@ -59072,78 +59381,786 @@ A4DA32 (base 16) Texas Instruments
Dallas TX 75243
US
-4C-21-D0 (hex) Sony Mobile Communications AB
-4C21D0 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+8C-14-B4 (hex) zte corporation
+8C14B4 (base 16) zte corporation
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
+ shenzhen guangdong 518057
+ CN
+
+3C-98-72 (hex) Sercomm Corporation.
+3C9872 (base 16) Sercomm Corporation.
+ 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
+ Miao-Lih Hsuan 115
+ TW
+
+8C-04-FF (hex) Technicolor CH USA Inc.
+8C04FF (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+FC-91-14 (hex) Technicolor CH USA Inc.
+FC9114 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+50-09-59 (hex) Technicolor CH USA Inc.
+500959 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+14-B7-F8 (hex) Technicolor CH USA Inc.
+14B7F8 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+B4-2A-0E (hex) Technicolor CH USA Inc.
+B42A0E (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+B0-18-86 (hex) SmarDTV
+B01886 (base 16) SmarDTV
+ Route de Genève 22
+ Cheseaux CH-1033
+ CH
+
+08-95-2A (hex) Technicolor CH USA Inc.
+08952A (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+88-F7-C7 (hex) Technicolor CH USA Inc.
+88F7C7 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+30-24-32 (hex) Intel Corporate
+302432 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+A8-99-69 (hex) Dell Inc.
+A89969 (base 16) Dell Inc.
+ One Dell Way
+ Round Rock TX 78682
+ US
+
+88-01-18 (hex) BLT Co
+880118 (base 16) BLT Co
+ Dongan-gu Burim-ro 170beon-gil 44
+ Anyangsi Kyunggido 14055
+ KR
+
+4C-21-D0 (hex) Sony Mobile Communications Inc
+4C21D0 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-30-75-12 (hex) Sony Mobile Communications AB
-307512 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+30-75-12 (hex) Sony Mobile Communications Inc
+307512 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-C4-3A-BE (hex) Sony Mobile Communications AB
-C43ABE (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+C4-3A-BE (hex) Sony Mobile Communications Inc
+C43ABE (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-40-B8-37 (hex) Sony Mobile Communications AB
-40B837 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+40-B8-37 (hex) Sony Mobile Communications Inc
+40B837 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-40-40-A7 (hex) Sony Mobile Communications AB
-4040A7 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+40-40-A7 (hex) Sony Mobile Communications Inc
+4040A7 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-94-CE-2C (hex) Sony Mobile Communications AB
-94CE2C (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+84-C7-EA (hex) Sony Mobile Communications Inc
+84C7EA (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-D0-51-62 (hex) Sony Mobile Communications AB
-D05162 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+84-17-EF (hex) Technicolor CH USA Inc.
+8417EF (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+10-59-17 (hex) Tonal
+105917 (base 16) Tonal
+ 1074 Folsom St
+ San Francisco 94103
+ US
+
+38-8B-59 (hex) Google, Inc.
+388B59 (base 16) Google, Inc.
+ 1600 Amphitheatre Parkway
+ Mountain View CA 94043
+ US
+
+94-CE-2C (hex) Sony Mobile Communications Inc
+94CE2C (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-25-E7 (hex) Sony Mobile Communications AB
-0025E7 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+D0-51-62 (hex) Sony Mobile Communications Inc
+D05162 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-40-2B-A1 (hex) Sony Mobile Communications AB
-402BA1 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-25-E7 (hex) Sony Mobile Communications Inc
+0025E7 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-12-EE (hex) Sony Mobile Communications AB
-0012EE (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+40-2B-A1 (hex) Sony Mobile Communications Inc
+402BA1 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-16-20 (hex) Sony Mobile Communications AB
-001620 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+34-0A-98 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+340A98 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+60-F1-8A (hex) HUAWEI TECHNOLOGIES CO.,LTD
+60F18A (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+00-12-EE (hex) Sony Mobile Communications Inc
+0012EE (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-84-C7-EA (hex) Sony Mobile Communications AB
-84C7EA (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-16-20 (hex) Sony Mobile Communications Inc
+001620 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
+28-9E-97 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+289E97 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+24-FA-F3 (hex) Shanghai Flexem Technology Co.,Ltd.
+24FAF3 (base 16) Shanghai Flexem Technology Co.,Ltd.
+ Room 804, C6 Building,No.52 Bay Valley Technology Park, Lane 1688 North Guoquan Road, Yangpu District.
+ Shanghai 200438
+ CN
+
+AC-DE-48 (hex) Private
+ACDE48 (base 16) Private
+
+0C-8C-24 (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD
+0C8C24 (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD
+ NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district
+ shenzhen guangdong 518000
+ CN
+
+7C-6B-9C (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+7C6B9C (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+ NO.18 HAIBIN ROAD,
+ DONG GUAN GUANG DONG 523860
+ CN
+
+1C-C3-EB (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+1CC3EB (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+ NO.18 HAIBIN ROAD,
+ DONG GUAN GUANG DONG 523860
+ CN
+
+30-D6-59 (hex) Merging Technologies SA
+30D659 (base 16) Merging Technologies SA
+ Le Verney 4
+ Puidoux Outside the U.S or Canada 1070
+ CH
+
+C4-95-00 (hex) Amazon Technologies Inc.
+C49500 (base 16) Amazon Technologies Inc.
+ P.O Box 8102
+ Reno NV 89507
+ US
+
+F0-F0-8F (hex) Nextek Solutions Pte Ltd
+F0F08F (base 16) Nextek Solutions Pte Ltd
+ 105 Cecil Street, #06-01 The Octagon
+ Singapore Singapore 069534
+ SG
+
+E4-D1-24 (hex) Mojo Networks, Inc.
+E4D124 (base 16) Mojo Networks, Inc.
+ 339 N.Bernardo Ave
+ Mountain View CA 94043
+ US
+
+28-3A-4D (hex) Cloud Network Technology (Samoa) Limited
+283A4D (base 16) Cloud Network Technology (Samoa) Limited
+ Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District
+ Chongqing Chongqing 401332
+ CN
+
+40-31-3C (hex) XIAOMI Electronics,CO.,LTD
+40313C (base 16) XIAOMI Electronics,CO.,LTD
+ Xiaomi Building, No.68 Qinghe Middle Street,Haidian District
+ Beijing Beijing 100085
+ CN
+
+CC-3A-DF (hex) Private
+CC3ADF (base 16) Private
+
+B4-CE-FE (hex) James Czekaj
+B4CEFE (base 16) James Czekaj
+ 41716 Waterfall Rd
+ Northville MI 48168
+ US
+
+E0-62-67 (hex) Xiaomi Communications Co Ltd
+E06267 (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+20-1A-06 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+201A06 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+B8-88-E3 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+B888E3 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone,, Jiangsu,
+ KUNSHAN SUZHOU 215300
+ CN
+
+00-26-22 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+002622 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+00-1E-EC (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+001EEC (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 25, THE 3RD Street
+ KUNSHAN CITY SUZHOU PROVINCE 215300
+ CN
+
+DC-0E-A1 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+DC0EA1 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone,, Jiangsu,
+ KUNSHAN SUZHOU 215300
+ CN
+
+FC-45-96 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+FC4596 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZON
+ KUNSHAN SUZHOU 215300
+ CN
+
+20-89-84 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+208984 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone
+ KUNSHAN SUZHOU 215300
+ CN
+
+58-03-FB (hex) Hangzhou Hikvision Digital Technology Co.,Ltd.
+5803FB (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd.
+ No.555 Qianmo Road
+ Hangzhou Zhejiang 310052
+ CN
+
+58-FD-BE (hex) Shenzhen Taikaida Technology Co., Ltd
+58FDBE (base 16) Shenzhen Taikaida Technology Co., Ltd
+ Shenzhen Baoan District Fuyong town Fengtang road Xintian building 613
+ shenzhen 518102
+ CN
+
+F8-CC-6E (hex) DEPO Electronics Ltd
+F8CC6E (base 16) DEPO Electronics Ltd
+ 12, kommunalnaya zona Krasnogorsk-Mitino
+ Krasnogorsk Moscow region 143404
+ RU
+
+80-6F-B0 (hex) Texas Instruments
+806FB0 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+14-94-2F (hex) USYS CO.,LTD.
+14942F (base 16) USYS CO.,LTD.
+ #911, SeoulTechnoPark, 232, Gongneung-ro, Nowon-gu
+ Seoul KS013
+ KR
+
+48-2C-A0 (hex) Xiaomi Communications Co Ltd
+482CA0 (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+B8-69-F4 (hex) Routerboard.com
+B869F4 (base 16) Routerboard.com
+ Mikrotikls SIA
+ Riga Riga LV1009
+ LV
+
+34-2E-B6 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+342EB6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+90-2B-D2 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+902BD2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+9C-7F-57 (hex) UNIC Memory Technology Co Ltd
+9C7F57 (base 16) UNIC Memory Technology Co Ltd
+ 15/F, Building B, Truth Plaza, No.7 Zhichun Road
+ Beijing Haidian District 102208
+ CN
+
+C4-6E-7B (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
+C46E7B (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
+ Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District,
+ Shenzhen Guangdong 518000
+ CN
+
+28-D0-CB (hex) Cambridge Communication Systems Ltd
+28D0CB (base 16) Cambridge Communication Systems Ltd
+ Victory House, Vision Park, Chivers Way, Histon
+ Cambridge CB24 9ZR
+ GB
+
+44-65-7F (hex) Calix Inc.
+44657F (base 16) Calix Inc.
+ 1035 North McDowell Boulevard
+ Petaluma MN 94954
+ US
+
+00-1A-31 (hex) SCAN COIN AB
+001A31 (base 16) SCAN COIN AB
+ Jagershillgatan 26
+ Malmö Skåne 21375
+ SE
+
+70-4F-08 (hex) Shenzhen Huisheng Information Technology Co., Ltd.
+704F08 (base 16) Shenzhen Huisheng Information Technology Co., Ltd.
+ Room 4A-205, Software Industry Base, Yuehai St
+ Nanshan District, Shenzhen Guangdong 518000
+ CN
+
+BC-A5-8B (hex) Samsung Electronics Co.,Ltd
+BCA58B (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+70-FD-46 (hex) Samsung Electronics Co.,Ltd
+70FD46 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+D0-7F-A0 (hex) Samsung Electronics Co.,Ltd
+D07FA0 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+F0-9F-FC (hex) SHARP Corporation
+F09FFC (base 16) SHARP Corporation
+ 1 Takumi-cho, Sakai-ku
+ Sakai City Osaka 590-8522
+ JP
+
+30-42-A1 (hex) ilumisys Inc. DBA Toggled
+3042A1 (base 16) ilumisys Inc. DBA Toggled
+ 1820 E. Big Beaver Road
+ Troy MI 48083
+ US
+
+20-DE-88 (hex) IC Realtime LLC
+20DE88 (base 16) IC Realtime LLC
+ 3050 N Andrews Ave Ext.
+ Pompano Beach FL 33064
+ US
+
+14-37-19 (hex) PT Prakarsa Visi Valutama
+143719 (base 16) PT Prakarsa Visi Valutama
+ Jl. Cideng Timur No.11D
+ Jakarta Pusat Indonesia 10130
+ ID
+
+58-2F-40 (hex) Nintendo Co.,Ltd
+582F40 (base 16) Nintendo Co.,Ltd
+ 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU
+ KYOTO KYOTO 601-8501
+ JP
+
+6C-6C-D3 (hex) Cisco Systems, Inc
+6C6CD3 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+30-16-8D (hex) ProLon
+30168D (base 16) ProLon
+ 17510 rue Charles, Suite 100
+ Mirabel Quebec J7J 1X9
+ CA
+
+80-30-E0 (hex) Hewlett Packard Enterprise
+8030E0 (base 16) Hewlett Packard Enterprise
+ 8000 Foothills Blvd.
+ Roseville CA 95747
+ US
+
+E8-5D-86 (hex) CHANG YOW TECHNOLOGIES INTERNATIONAL CO.,LTD.
+E85D86 (base 16) CHANG YOW TECHNOLOGIES INTERNATIONAL CO.,LTD.
+ No 88 Shuren 6th St Wufong District
+ Taichung 413
+ TW
+
+1C-25-E1 (hex) China Mobile IOT Company Limited
+1C25E1 (base 16) China Mobile IOT Company Limited
+ NO.8 Yu Ma Road, NanAn Area
+ Chongqing Chongqing 401336
+ CN
+
+AC-54-74 (hex) China Mobile IOT Company Limited
+AC5474 (base 16) China Mobile IOT Company Limited
+ NO.8 Yu Ma Road, NanAn Area
+ Chongqing Chongqing 401336
+ CN
+
+00-40-84 (hex) Honeywell International HPS
+004084 (base 16) Honeywell International HPS
+
+ Fort Washington PA 19034
+ US
+
+64-5D-86 (hex) Intel Corporate
+645D86 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+8C-92-46 (hex) Oerlikon Textile Gmbh&Co.KG
+8C9246 (base 16) Oerlikon Textile Gmbh&Co.KG
+ NO.9 Changyang Street
+ Suzhou Jiangsu 215000
+ CN
+
+7C-24-0C (hex) Telechips, Inc.
+7C240C (base 16) Telechips, Inc.
+ 19F~23F,Luther Bldg.42, Olympic-ro 35da-gil, Songpa-gu,
+ Seoul Seoul 05510
+ KR
+
+CC-F0-FD (hex) China Mobile (Hangzhou) Information Technology Co., Ltd.
+CCF0FD (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd.
+ No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District, Hangzhou, Zhejiang
+ Hangzhou Zhejiang 310000
+ CN
+
+4C-01-43 (hex) eero inc.
+4C0143 (base 16) eero inc.
+ 660 3rd Street
+ San Francisco CA 94107
+ US
+
+9C-AA-1B (hex) Microsoft Corporation
+9CAA1B (base 16) Microsoft Corporation
+ One Microsoft Way
+ REDMOND WA 98052
+ US
+
+18-D7-17 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+18D717 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+ NO.18 HAIBIN ROAD,
+ DONG GUAN GUANG DONG 523860
+ CN
+
+0C-9A-42 (hex) FN-LINK TECHNOLOGY LIMITED
+0C9A42 (base 16) FN-LINK TECHNOLOGY LIMITED
+ A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District
+ SHENZHEN GUANGDONG 518100
+ CN
+
+60-4B-AA (hex) Magic Leap, Inc.
+604BAA (base 16) Magic Leap, Inc.
+ 1855 Griffin Rd, Room B454
+ Dania Beach FL 33004
+ US
+
+54-81-2D (hex) PAX Computer Technology(Shenzhen) Ltd.
+54812D (base 16) PAX Computer Technology(Shenzhen) Ltd.
+ 4/F, No.3 Building, Software Park, Second Central Science-Tech Road, High-Tech
+ Shenzhen GuangDong 518057
+ CN
+
+30-A1-FA (hex) HUAWEI TECHNOLOGIES CO.,LTD
+30A1FA (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+88-10-8F (hex) HUAWEI TECHNOLOGIES CO.,LTD
+88108F (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+0C-53-31 (hex) ETH Zurich
+0C5331 (base 16) ETH Zurich
+ Dept. Computer Science, Universitätstr. 6
+ Zurich ZH 8092
+ CH
+
+F4-63-1F (hex) HUAWEI TECHNOLOGIES CO.,LTD
+F4631F (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+24-FB-65 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+24FB65 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+EC-84-B4 (hex) CIG SHANGHAI CO LTD
+EC84B4 (base 16) CIG SHANGHAI CO LTD
+ 5th Floor, Building 8 No 2388 Chenhang Road
+ SHANGHAI 201114
+ CN
+
+EC-B3-13 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT
+ECB313 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT
+ SONGGANG
+ SHENZHEN GUANGDONG 518105
+ CN
+
+8C-FE-74 (hex) Ruckus Wireless
+8CFE74 (base 16) Ruckus Wireless
+ 350 West Java Drive
+ Sunnyvale CA 94089
+ US
+
+84-6A-66 (hex) Sumitomo Kizai Co.,Ltd.
+846A66 (base 16) Sumitomo Kizai Co.,Ltd.
+ 1-45-1higashiikebukuro
+ tosimaku tokyo 170-0013
+ JP
+
+DC-37-57 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
+DC3757 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
+ Phase 3, Bayan Lepas FIZ
+ Bayan Lepas Penang 11900
+ MY
+
+00-90-04 (hex) 3COM EUROPE LTD
+009004 (base 16) 3COM EUROPE LTD
+ 3COM CENTRE, BOUNDARY WAY
+ HERTS. HP2 7YU
+ GB
+
+00-50-99 (hex) 3COM EUROPE LTD
+005099 (base 16) 3COM EUROPE LTD
+ BOUNDARY WAY
+ HERTS. HP2 7YU
+ GB
+
+08-00-4E (hex) 3COM EUROPE LTD
+08004E (base 16) 3COM EUROPE LTD
+ 3COM CENTRE
+ UNITED KINGDOM
+ GB
+
+00-D0-96 (hex) 3COM EUROPE LTD
+00D096 (base 16) 3COM EUROPE LTD
+ BOUNDARY WAY
+ UNITED KINGDOM
+ GB
+
+00-30-1E (hex) 3COM EUROPE LTD
+00301E (base 16) 3COM EUROPE LTD
+ BOUNDARY WAY
+ UNITED KINGDOM
+ GB
+
+00-0A-5E (hex) 3COM
+000A5E (base 16) 3COM
+ 5400 Bayfront Plaza
+ Santa Clara CA 95052-8145
+ US
+
+00-06-8C (hex) 3COM
+00068C (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-01-03 (hex) 3COM
+000103 (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+02-60-8C (hex) 3COM
+02608C (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-1B-6E (hex) Keysight Technologies, Inc.
+001B6E (base 16) Keysight Technologies, Inc.
+ 1400 Fountaingrove Pkwy.
+ Santa Rosa CA 95403
+ US
+
+00-8C-FA (hex) INVENTEC CORPORATION
+008CFA (base 16) INVENTEC CORPORATION
+ No. 255, Jen-Ho Road Sec. 2, 33547,
+ Tachi Taoyuan 33547
+ TW
+
+C4-23-A2 (hex) PT. Emsonic Indonesia
+C423A2 (base 16) PT. Emsonic Indonesia
+ Jl.Timor Blok E5, MM2100 Industrial Town Jatiwangi Cikarang Barat
+ Bekasi Jawa Barat 17530
+ ID
+
+B4-CB-57 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+B4CB57 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+ NO.18 HAIBIN ROAD,
+ DONG GUAN GUANG DONG 523860
+ CN
+
+BC-B2-2B (hex) EM-Tech
+BCB22B (base 16) EM-Tech
+ 40, Changwon-daero 1144beon-gil
+ Seongsan-gu Changwon Gyeongsangnam-do KR 642-120
+ KR
+
+94-91-7F (hex) ASKEY COMPUTER CORP
+94917F (base 16) ASKEY COMPUTER CORP
+ 10F,No.119,JIANKANG RD,ZHONGHE DIST
+ NEW TAIPEI TAIWAN 23585
+ TW
+
+C8-BA-E9 (hex) QDIS
+C8BAE9 (base 16) QDIS
+ #512, Buliding B, 168 GaSanDigital 1st, GeumChun-Gu
+ SEOUL 08507
+ KR
+
+B8-6A-97 (hex) Edgecore Networks Corporation
+B86A97 (base 16) Edgecore Networks Corporation
+ 1 Creation RD 3.
+ Hsinchu 30077
+ TW
+
+94-29-8D (hex) Shanghai AdaptComm Technology Co., Ltd.
+94298D (base 16) Shanghai AdaptComm Technology Co., Ltd.
+ 3rd Floor, Building 14, No. 518 Xinzhuan Road, Songjiang District,
+ Shanghai 201600
+ CN
+
+EC-79-F2 (hex) Startel
+EC79F2 (base 16) Startel
+ Xi Chuang Industrial Park,Second industrial district of Guan Long Village,Xili town ,Nanshan District
+ Shenzhen Guangdong 518055
+ CN
+
+28-31-66 (hex) vivo Mobile Communication Co., Ltd.
+283166 (base 16) vivo Mobile Communication Co., Ltd.
+ #283,BBK Road
+ Wusha,Chang'An DongGuan City,Guangdong, 523860
+ CN
+
+4C-12-65 (hex) ARRIS Group, Inc.
+4C1265 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+00-90-7F (hex) WatchGuard Technologies, Inc.
+00907F (base 16) WatchGuard Technologies, Inc.
+ 605 Fifth Ave. S
+ Seattle WA 98104-3892
+ US
+
+F0-B0-14 (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH
+F0B014 (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH
+ Alt-Moabit 95
+ Berlin Berlin 10559
+ DE
+
+A8-10-87 (hex) Texas Instruments
+A81087 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+AC-86-74 (hex) Open Mesh, Inc.
+AC8674 (base 16) Open Mesh, Inc.
+ 111 SW 5th Ave Ste1150
+ Portland OR 97204
+ US
+
+18-E8-29 (hex) Ubiquiti Networks Inc.
+18E829 (base 16) Ubiquiti Networks Inc.
+ 2580 Orchard Pkwy
+ San Jose CA 95131
+ US
+
+18-1D-EA (hex) Intel Corporate
+181DEA (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+F0-D7-DC (hex) Wesine (Wuhan) Technology Co., Ltd.
+F0D7DC (base 16) Wesine (Wuhan) Technology Co., Ltd.
+ 10th Floor, Building 2, SBI Venture Street, Hongshan District
+ Wuhan Hubei 430074
+ CN
+
+44-E4-EE (hex) Wistron Neweb Corporation
+44E4EE (base 16) Wistron Neweb Corporation
+ No.20,Park Avenue II,Hsinchu Science Park
+ Hsin-Chu R.O.C. 308
+ TW
+
58-46-E1 (hex) Baxter International Inc
5846E1 (base 16) Baxter International Inc
One Baxter Parkway
@@ -61601,12 +62618,6 @@ A49F85 (base 16) Lyve Minds, Inc
Cupertino CA 95014
US
-7C-D3-0A (hex) INVENTEC Corporation
-7CD30A (base 16) INVENTEC Corporation
- Inventec Building, 66 Hou-Kang Street
- Taipei 111
- TW
-
34-81-C4 (hex) AVM GmbH
3481C4 (base 16) AVM GmbH
Alt-Moabit 95
@@ -68417,12 +69428,6 @@ A893E6 (base 16) JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LT
WanChai
HK
-00-1E-80 (hex) Last Mile Ltd.
-001E80 (base 16) Last Mile Ltd.
- 12/F VIP Commercial Centre
- Tsimshatsui
- HK
-
00-1E-FC (hex) JSC MASSA-K
001EFC (base 16) JSC MASSA-K
15, A, Pirogovskaya nab.
@@ -69107,12 +70112,6 @@ A893E6 (base 16) JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LT
Taastrup 2630
DK
-00-1B-84 (hex) Scan Engineering Telecom
-001B84 (base 16) Scan Engineering Telecom
- Svobody str. 75
- Voronezh 394030
- RU
-
00-1B-D1 (hex) SOGESTMATIC
001BD1 (base 16) SOGESTMATIC
409 Route de la Gare
@@ -69239,12 +70238,6 @@ A893E6 (base 16) JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LT
George Town, Cayman Islands 00000
KY
-00-1A-C5 (hex) BreakingPoint Systems, Inc.
-001AC5 (base 16) BreakingPoint Systems, Inc.
- 3900 N. Capital of Texas Hwy
- Austin TX 78746
- US
-
00-1A-BB (hex) Fontal Technology Incorporation
001ABB (base 16) Fontal Technology Incorporation
Rm.522, Bldg. 52, 195, Sec. 4, ChungHsing Rd., Chutung
@@ -70916,12 +71909,6 @@ A893E6 (base 16) JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LT
Saratov Saratov region 410600
RU
-00-13-A3 (hex) Siemens Com CPE Devices
-0013A3 (base 16) Siemens Com CPE Devices
- 4849 Alpha Road
- Dallas Texas 75244
- US
-
00-13-9E (hex) Ciara Technologies Inc.
00139E (base 16) Ciara Technologies Inc.
9300 Trans Canada Highway
@@ -76685,12 +77672,6 @@ A06A00 (base 16) Verilink Corporation
SAN JOSE CA 95134
US
-00-50-DA (hex) 3COM CORPORATION
-0050DA (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-50-F9 (hex) Sensormatic Electronics LLC
0050F9 (base 16) Sensormatic Electronics LLC
1501 Yamato Rd
@@ -76943,12 +77924,6 @@ A06A00 (base 16) Verilink Corporation
WESTLAKE VILLAGE CA 91362
US
-00-10-4B (hex) 3COM CORPORATION
-00104B (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-06-29 (hex) IBM Corp
000629 (base 16) IBM Corp
3039 E Cornwallis Road
@@ -77465,12 +78440,6 @@ A06A00 (base 16) Verilink Corporation
SAN DIEGO CA 92121
US
-00-E0-5C (hex) Panasonic Healthcare Co., Ltd.
-00E05C (base 16) Panasonic Healthcare Co., Ltd.
- 2131-1 Minamikata
- Toon City Ehime
- JP
-
00-E0-87 (hex) LeCroy - Networking Productions Division
00E087 (base 16) LeCroy - Networking Productions Division
25 BURLINGTON MALL ROAD
@@ -77741,12 +78710,6 @@ A06A00 (base 16) Verilink Corporation
D-30165 HANNOVER
DE
-00-60-97 (hex) 3COM CORPORATION
-006097 (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-60-E3 (hex) ARBIN INSTRUMENTS
0060E3 (base 16) ARBIN INSTRUMENTS
3206 LONGMIRE DRIVE
@@ -77873,12 +78836,6 @@ A06A00 (base 16) Verilink Corporation
231
JP
-00-60-08 (hex) 3COM CORPORATION
-006008 (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-60-EF (hex) FLYTECH TECHNOLOGY CO., LTD.
0060EF (base 16) FLYTECH TECHNOLOGY CO., LTD.
No.168 Sing-ai Rd., Neihu District
@@ -78185,12 +79142,6 @@ A06A00 (base 16) Verilink Corporation
CAMBRIDGE CB5 8QE
GB
-00-A0-24 (hex) 3COM CORPORATION
-00A024 (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-A0-8B (hex) ASTON ELECTRONIC DESIGNS LTD.
00A08B (base 16) ASTON ELECTRONIC DESIGNS LTD.
123/127 DEEPCUT BRIDGE ROAD
@@ -78407,12 +79358,6 @@ A06A00 (base 16) Verilink Corporation
BURLINGTON MA 01803
US
-00-20-B5 (hex) YASKAWA ELECTRIC CORPORATION
-0020B5 (base 16) YASKAWA ELECTRIC CORPORATION
- 2-1 KUROSAKI-SHIROISHI
-
- JP
-
00-20-72 (hex) WORKLINK INNOVATIONS
002072 (base 16) WORKLINK INNOVATIONS
2452 ARMSTRONG STREET
@@ -79325,12 +80270,6 @@ A06A00 (base 16) Verilink Corporation
Neckartenzlingen D-72654
DE
-00-60-8C (hex) 3COM CORPORATION
-00608C (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-80-4E (hex) APEX COMPUTER COMPANY
00804E (base 16) APEX COMPUTER COMPANY
4500 150TH AVENUE, NE
@@ -79931,18 +80870,6 @@ A01B29 (base 16) Sagemcom Broadband SAS
Rueil Malmaison Cedex Hauts de Seine 92848
FR
-00-23-5A (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-00235A (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO 25, The 3rd street,
- KuanShan SUZHOU 215300
- CN
-
-00-1B-38 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-001B38 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 25, THE 3RD AVENUE
- KUNSHAN CITY SUZHOU PROVINCE 215300
- CN
-
E4-6F-13 (hex) D-Link International
E46F13 (base 16) D-Link International
1 Internal Business Park, #03-12,The Synergy, Singapore
@@ -80801,12 +81728,6 @@ F40E22 (base 16) Samsung Electronics Co.,Ltd
Gumi Gyeongbuk 730-350
KR
-BC-F2-AF (hex) devolo AG
-BCF2AF (base 16) devolo AG
- Charlottenburger Allee 60
- Aachen 52068
- DE
-
02-70-B3 (hex) DATA RECALL LTD.
0270B3 (base 16) DATA RECALL LTD.
SONDES PLACE
@@ -82025,24 +82946,6 @@ AC040B (base 16) Peloton Interactive, Inc
YOKOHAMA KANAGAWA-KEN 222-0011
JP
-44-32-C8 (hex) Technicolor CH USA Inc.
-4432C8 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-E0-88-5D (hex) Technicolor CH USA Inc.
-E0885D (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-80-29-94 (hex) Technicolor CH USA Inc.
-802994 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
20-6A-8A (hex) Wistron Infocomm (Zhongshan) Corporation
206A8A (base 16) Wistron Infocomm (Zhongshan) Corporation
168# First Avenue,Kunshan Export Processing Zone
@@ -83828,12 +84731,6 @@ F48B32 (base 16) Xiaomi Communications Co Ltd
NO.68, Qinghe Middle Street Haidian District, Beijing 100085
CN
-00-60-BD (hex) Enginuity Communications
-0060BD (base 16) Enginuity Communications
- 2900 TOWERVIEW ROAD
- HERNDON VA 21071
- US
-
AC-83-F3 (hex) AMPAK Technology, Inc.
AC83F3 (base 16) AMPAK Technology, Inc.
No.1,Jen Ai Road Hsinchu Industrial Park, Hukou
@@ -84602,12 +85499,6 @@ C4AE12 (base 16) Samsung Electronics Co.,Ltd
Hsinchu Taiwan ROC. 30352
TW
-80-B2-34 (hex) Technicolor CH USA Inc.
-80B234 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
B8-77-C3 (hex) METER Group
B877C3 (base 16) METER Group
2365 NE Hopkins Court
@@ -85622,1107 +86513,6 @@ BC5451 (base 16) Samsung Electronics Co.,Ltd
Piscataway NJ 08554
US
-BC-C3-1B (hex) Kygo Life AS
-BCC31B (base 16) Kygo Life AS
- Sjolyst Plass 3
- Oslo 0278
- NO
-
-FC-D6-BD (hex) Robert Bosch GmbH
-FCD6BD (base 16) Robert Bosch GmbH
- AE-BE/EKE
- Leonberg BW 71206
- DE
-
-78-2D-7E (hex) TRENDnet, Inc.
-782D7E (base 16) TRENDnet, Inc.
- 20675 Manhattan Place
- Torrance CA 90501
- US
-
-28-AD-3E (hex) Shenzhen TONG BO WEI Technology CO.,LTD
-28AD3E (base 16) Shenzhen TONG BO WEI Technology CO.,LTD
- Longhua District, Dalang street Langkou community Huarong Road Peng Tengda Industrial Park 4 5 floor
- SHENZHEN guangdong 518109
- CN
-
-B0-6E-BF (hex) ASUSTek COMPUTER INC.
-B06EBF (base 16) ASUSTek COMPUTER INC.
- 15,Li-Te Rd., Peitou, Taipei 112, Taiwan
- Taipei Taiwan 112
- TW
-
-48-BA-4E (hex) Hewlett Packard
-48BA4E (base 16) Hewlett Packard
- 11445 Compaq Center Drive
- Houston TX 77070
- US
-
-FC-65-DE (hex) Amazon Technologies Inc.
-FC65DE (base 16) Amazon Technologies Inc.
- P.O Box 8102
- Reno NV 89507
- US
-
-F0-92-B4 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD
-F092B4 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD
- FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road,
- Chengdu Sichuan 610000
- CN
-
-70-7D-95 (hex) Shenzhen City LinwlanTechnology Co. Ltd.
-707D95 (base 16) Shenzhen City LinwlanTechnology Co. Ltd.
- 106 village road , manhole street Baoan district .
- Shenzhen Guangdong 518125
- CN
-
-28-D9-3E (hex) Telecor Inc.
-28D93E (base 16) Telecor Inc.
- 6205 Kestrel Road
- Mississauga Ontario L5T 2A1
- CA
-
-8C-0F-83 (hex) Angie Hospitality LLC
-8C0F83 (base 16) Angie Hospitality LLC
- 12465 S Fort St, Ste 300
- Draper UT 84020-9021
- US
-
-00-50-FC (hex) Edimax Technology Co. Ltd.
-0050FC (base 16) Edimax Technology Co. Ltd.
- No. 278, Xinhu 1st Road
- Taipei City Neihu Dist 248
- TW
-
-74-83-EF (hex) Arista Networks
-7483EF (base 16) Arista Networks
- 5453 Great America Parkway
- Santa Clara CA 95054
- US
-
-00-1C-73 (hex) Arista Networks
-001C73 (base 16) Arista Networks
- 5470 Great America Pkwy
- Santa Clara California 95054
- US
-
-38-AD-8E (hex) New H3C Technologies Co., Ltd
-38AD8E (base 16) New H3C Technologies Co., Ltd
- 466 Changhe Road, Binjiang District
- Hangzhou Zhejiang 310052
- CN
-
-00-12-48 (hex) Dell EMC
-001248 (base 16) Dell EMC
- 176 South Street
- Hopkinton MA 01748
- US
-
-00-01-44 (hex) Dell EMC
-000144 (base 16) Dell EMC
- 228 South St.
- Hopkinton MA 01748
- US
-
-00-BF-61 (hex) Samsung Electronics Co.,Ltd
-00BF61 (base 16) Samsung Electronics Co.,Ltd
- 129, Samsung-ro, Youngtongl-Gu
- Suwon Gyeonggi-Do 16677
- KR
-
-30-9F-FB (hex) Ardomus Networks Corporation
-309FFB (base 16) Ardomus Networks Corporation
- 4F,No. 6 Innovation Road II, Hsinchu Science Park
- Hsinchu 300
- TW
-
-E4-BD-4B (hex) zte corporation
-E4BD4B (base 16) zte corporation
- 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
- shenzhen guangdong 518057
- CN
-
-6C-56-97 (hex) Amazon Technologies Inc.
-6C5697 (base 16) Amazon Technologies Inc.
- P.O Box 8102
- Reno NV 89507
- US
-
-3C-A5-81 (hex) vivo Mobile Communication Co., Ltd.
-3CA581 (base 16) vivo Mobile Communication Co., Ltd.
- #283,BBK Road
- Wusha,Chang'An DongGuan City,Guangdong, 523860
- CN
-
-F4-EA-B5 (hex) Aerohive Networks Inc.
-F4EAB5 (base 16) Aerohive Networks Inc.
- 1011 McCarthy Blvd
- Milpitas CA 95035
- US
-
-F8-20-55 (hex) Green Information System
-F82055 (base 16) Green Information System
- #202(Shopping center), Woldong-ro 28, Buk-gu
- Gwangju 61153
- KR
-
-78-5C-28 (hex) Prime Motion Inc.
-785C28 (base 16) Prime Motion Inc.
- Akaho 1134-12
- Komagane Nagano 399-4117
- JP
-
-94-49-96 (hex) WiSilica Inc
-944996 (base 16) WiSilica Inc
- 23282 Mill Creek Dr #340
- Laguna Hills CA 92653
- US
-
-00-26-A8 (hex) DAEHAP HYPER-TECH
-0026A8 (base 16) DAEHAP HYPER-TECH
- Mega center #1108, SK Techno-Park, #190-1, Sangdaewon-Dong, Jungwon-Gu
- Seongnam Gyeonggi-Do 462-807
- KR
-
-F8-7B-20 (hex) Cisco Systems, Inc
-F87B20 (base 16) Cisco Systems, Inc
- 80 West Tasman Drive
- San Jose CA 94568
- US
-
-F8-1D-0F (hex) Hitron Technologies. Inc
-F81D0F (base 16) Hitron Technologies. Inc
- No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C
- Hsin-chu Taiwan 300
- TW
-
-30-FB-94 (hex) Shanghai Fangzhiwei Information Technology CO.,Ltd.
-30FB94 (base 16) Shanghai Fangzhiwei Information Technology CO.,Ltd.
- The 17th Building A Unit,No. 1688 Lianhang Road,Minhang District,Shanghai City
- Shanghai 201100
- CN
-
-08-BA-22 (hex) Swaive Corporation
-08BA22 (base 16) Swaive Corporation
- 3565 Kettmann Road
- San Jose CA 95121
- US
-
-F8-0C-F3 (hex) LG Electronics (Mobile Communications)
-F80CF3 (base 16) LG Electronics (Mobile Communications)
- 60-39, Gasan-dong, Geumcheon-gu
- Seoul 153-801
- KR
-
-30-76-6F (hex) LG Electronics (Mobile Communications)
-30766F (base 16) LG Electronics (Mobile Communications)
- 60-39, Gasan-dong, Geumcheon-gu
- Seoul 153-801
- KR
-
-8C-3A-E3 (hex) LG Electronics (Mobile Communications)
-8C3AE3 (base 16) LG Electronics (Mobile Communications)
- 60-39, Gasan-dong, Geumcheon-gu
- Seoul 153-801
- KR
-
-94-2A-3F (hex) Diversey Inc
-942A3F (base 16) Diversey Inc
- 2415 Cascade Pointe Blvd
- Charlotte NC 28208
- US
-
-78-F8-82 (hex) LG Electronics (Mobile Communications)
-78F882 (base 16) LG Electronics (Mobile Communications)
- 60-39, Gasan-dong, Geumcheon-gu
- Seoul 153-801
- KR
-
-0C-61-11 (hex) Anda Technologies SAC
-0C6111 (base 16) Anda Technologies SAC
- Av. Santa Cruz 888, Miraflores
- Lima Peru Lima18
- PE
-
-B8-F7-4A (hex) RCNTEC
-B8F74A (base 16) RCNTEC
- Polkovaya street 3
- Moscow 127018
- RU
-
-C8-D1-2A (hex) Comtrend Corporation
-C8D12A (base 16) Comtrend Corporation
- 3F-1, No. 10, Lane 609, Chung Hsin Road, Sec 5, San Chung Dist.
- New Taipei City Taiwan 24159
- TW
-
-B4-F1-DA (hex) LG Electronics (Mobile Communications)
-B4F1DA (base 16) LG Electronics (Mobile Communications)
- 60-39, Gasan-dong, Geumcheon-gu
- Seoul 153-801
- KR
-
-00-21-FB (hex) LG Electronics (Mobile Communications)
-0021FB (base 16) LG Electronics (Mobile Communications)
- 60-39, Gasan-dong, Geumcheon-gu
- Seoul 153-801
- KR
-
-D0-13-FD (hex) LG Electronics (Mobile Communications)
-D013FD (base 16) LG Electronics (Mobile Communications)
- 60-39, Gasan-dong, Geumcheon-gu
- Seoul 153-801
- KR
-
-A8-B8-6E (hex) LG Electronics (Mobile Communications)
-A8B86E (base 16) LG Electronics (Mobile Communications)
- 60-39, Gasan-dong, Geumcheon-gu
- Seoul 153-801
- KR
-
-DC-4F-22 (hex) Espressif Inc.
-DC4F22 (base 16) Espressif Inc.
- Room 204, Building 2, 690 Bibo Road, Pudong New Area
- Shanghai Shanghai 201203
- CN
-
-34-2A-F1 (hex) Texas Instruments
-342AF1 (base 16) Texas Instruments
- 12500 TI Blvd
- Dallas TX 75243
- US
-
-70-E5-6E (hex) Texas Instruments
-70E56E (base 16) Texas Instruments
- 12500 TI Blvd
- Dallas TX 75243
- US
-
-F0-85-C1 (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
-F085C1 (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
- Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District,
- Shenzhen Guangdong 518000
- CN
-
-C8-DE-C9 (hex) Coriant
-C8DEC9 (base 16) Coriant
- 1415 W. Diehl Rd
- Naperville IL 60563
- US
-
-38-0E-4D (hex) Cisco Systems, Inc
-380E4D (base 16) Cisco Systems, Inc
- 80 West Tasman Drive
- San Jose CA 94568
- US
-
-FC-9D-D8 (hex) Beijing TongTongYiLian Science and Technology Ltd.
-FC9DD8 (base 16) Beijing TongTongYiLian Science and Technology Ltd.
- Room 301,Zone 3,Building 9,No.8 Dongbeiwang West Road,Haidian District,Beijing
- BEIJING BEIJING 100193
- CN
-
-04-B1-67 (hex) Xiaomi Communications Co Ltd
-04B167 (base 16) Xiaomi Communications Co Ltd
- The Rainbow City of China Resources
- NO.68, Qinghe Middle Street Haidian District, Beijing 100085
- CN
-
-38-AD-BE (hex) New H3C Technologies Co., Ltd
-38ADBE (base 16) New H3C Technologies Co., Ltd
- 466 Changhe Road, Binjiang District
- Hangzhou Zhejiang 310052
- CN
-
-20-78-52 (hex) Nokia
-207852 (base 16) Nokia
- Karaportti 3
- Espoo Finland 02610
- FI
-
-AC-64-17 (hex) Siemens AG - Industrial Automation - EWA
-AC6417 (base 16) Siemens AG - Industrial Automation - EWA
- Werner-von-Siemens Strasse 50
- Amberg 92224
- DE
-
-CC-5D-4E (hex) Zyxel Communications Corporation
-CC5D4E (base 16) Zyxel Communications Corporation
- No. 6 Innovation Road II, Science Park
- Hsichu Taiwan 300
- TW
-
-40-4A-03 (hex) Zyxel Communications Corporation
-404A03 (base 16) Zyxel Communications Corporation
- No. 6 Innovation Road II, Science Park
- Hsichu Taiwan 300
- TW
-
-00-13-49 (hex) Zyxel Communications Corporation
-001349 (base 16) Zyxel Communications Corporation
- No. 6 Innovation Road II, Science Park
- Hsichu Taiwan 300
- TW
-
-1C-74-0D (hex) Zyxel Communications Corporation
-1C740D (base 16) Zyxel Communications Corporation
- No. 6 Innovation Road II, Science Park
- Hsichu Taiwan 300
- TW
-
-A0-E4-CB (hex) Zyxel Communications Corporation
-A0E4CB (base 16) Zyxel Communications Corporation
- No. 6 Innovation Road II, Science Park
- Hsichu Taiwan 300
- TW
-
-5C-6A-80 (hex) Zyxel Communications Corporation
-5C6A80 (base 16) Zyxel Communications Corporation
- No. 6 Innovation Road II, Science Park
- Hsichu Taiwan 300
- TW
-
-5C-E2-8C (hex) Zyxel Communications Corporation
-5CE28C (base 16) Zyxel Communications Corporation
- No. 6 Innovation Road II, Science Park
- Hsichu Taiwan 300
- TW
-
-A8-EE-C6 (hex) Muuselabs NV/SA
-A8EEC6 (base 16) Muuselabs NV/SA
- Rue du Tocsin 12
- Brussels 1000
- BE
-
-A0-9D-C1 (hex) China Dragon Technology Limited
-A09DC1 (base 16) China Dragon Technology Limited
- B4 Bldg.Haoshan 1st Industry Park,
- Shenzhen Guangdong 518104
- CN
-
-38-43-7D (hex) Compal Broadband Networks, Inc.
-38437D (base 16) Compal Broadband Networks, Inc.
- 13F., No.1, Taiyuan 1st St.
- Zhubei City Hsinchu County 30265
- TW
-
-5C-86-C1 (hex) DONGGUAN SOLUM ELECTRONICS CO.,LTD
-5C86C1 (base 16) DONGGUAN SOLUM ELECTRONICS CO.,LTD
- NO.157,13 Coastal Way TPFTZ
- TIANJIN 300461
- CN
-
-6C-DD-30 (hex) Cisco Systems, Inc
-6CDD30 (base 16) Cisco Systems, Inc
- 80 West Tasman Drive
- San Jose CA 94568
- US
-
-00-80-6C (hex) Secure Systems & Services
-00806C (base 16) Secure Systems & Services
- 24, Chemin de la Pouranque
- F-13752 LES PENNES MIRABEAU CS30084
- FR
-
-00-02-61 (hex) Tilgin AB
-000261 (base 16) Tilgin AB
- Finlandsgatan 40
-
- SE
-
-AC-E2-D3 (hex) Hewlett Packard
-ACE2D3 (base 16) Hewlett Packard
- 11445 Compaq Center Drive
- Houston TX 77070
- US
-
-28-2F-C2 (hex) Automotive Data Solutions
-282FC2 (base 16) Automotive Data Solutions
- 8400 rue Bougainville
- Montreal Quebec H4P2G1
- CA
-
-00-1D-38 (hex) Seagate Technology
-001D38 (base 16) Seagate Technology
- M/S NW1F01
- Longmont CO 80503
- US
-
-68-3E-02 (hex) SIEMENS AG, Digital Factory, Motion Control System
-683E02 (base 16) SIEMENS AG, Digital Factory, Motion Control System
- Varey Road
- Congleton Cheshire CW12 1PH
- GB
-
-34-E3-80 (hex) Genexis B.V.
-34E380 (base 16) Genexis B.V.
- Lodewijkstraat 1A
- Eindhoven 5652AC
- NL
-
-2C-B2-1A (hex) Phicomm (Shanghai) Co., Ltd.
-2CB21A (base 16) Phicomm (Shanghai) Co., Ltd.
- 3666 SiXian Rd.,Songjiang District
- Shanghai Shanghai 201616
- CN
-
-CC-81-DA (hex) Phicomm (Shanghai) Co., Ltd.
-CC81DA (base 16) Phicomm (Shanghai) Co., Ltd.
- 3666 SiXian Rd.,Songjiang District
- Shanghai Shanghai 201616
- CN
-
-B8-07-16 (hex) vivo Mobile Communication Co., Ltd.
-B80716 (base 16) vivo Mobile Communication Co., Ltd.
- #283,BBK Road
- Wusha,Chang'An DongGuan City,Guangdong, 523860
- CN
-
-C8-DF-84 (hex) Texas Instruments
-C8DF84 (base 16) Texas Instruments
- 12500 TI Blvd
- Dallas TX 75243
- US
-
-5C-0E-8B (hex) Extreme Networks, Inc.
-5C0E8B (base 16) Extreme Networks, Inc.
- 475 Half Day Road
- Lincolnshire IL 60069
- US
-
-B4-C7-99 (hex) Extreme Networks, Inc.
-B4C799 (base 16) Extreme Networks, Inc.
- 475 Half Day Road
- Lincolnshire IL 60069
- US
-
-74-67-F7 (hex) Extreme Networks, Inc.
-7467F7 (base 16) Extreme Networks, Inc.
- 1 Zebra Plaza
- Holtsville NY 11742
- US
-
-98-00-74 (hex) Raisecom Technology CO., LTD
-980074 (base 16) Raisecom Technology CO., LTD
- No. 11, East Area, No. 10 Block, East Xibeiwang Road
- Beijing 100094
- CN
-
-18-C1-9D (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
-18C19D (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
- Phase 3, Bayan Lepas FIZ
- Bayan Lepas Penang 11900
- MY
-
-00-E0-2B (hex) Extreme Networks, Inc.
-00E02B (base 16) Extreme Networks, Inc.
- 10460 BANDLEY DRIVE
- CUPERINT0 CA 95014
- US
-
-A4-86-AE (hex) Quectel Wireless Solutions
-A486AE (base 16) Quectel Wireless Solutions
- No.1801 Hongmei Road, Xuhui District
- Shanghai 200233
- CN
-
-70-26-05 (hex) SONY Visual Products Inc.
-702605 (base 16) SONY Visual Products Inc.
- 2-10-1 Osaki
- Shinagawa-ku Tokyo 141-8610
- JP
-
-5C-5F-67 (hex) Intel Corporate
-5C5F67 (base 16) Intel Corporate
- Lot 8, Jalan Hi-Tech 2/3
- Kulim Kedah 09000
- MY
-
-7C-76-35 (hex) Intel Corporate
-7C7635 (base 16) Intel Corporate
- Lot 8, Jalan Hi-Tech 2/3
- Kulim Kedah 09000
- MY
-
-DC-48-B2 (hex) Baraja Pty. Ltd.
-DC48B2 (base 16) Baraja Pty. Ltd.
- 36 Bradfield Road
- West Lindfield NSW 2070
- AU
-
-00-01-23 (hex) Schneider Electric Japan Holdings Ltd.
-000123 (base 16) Schneider Electric Japan Holdings Ltd.
- Schneider Electric Osaka Building
- 4-4-9 Kitahama Chuo-ku, Osaka 541-0041
- JP
-
-D8-63-75 (hex) Xiaomi Communications Co Ltd
-D86375 (base 16) Xiaomi Communications Co Ltd
- The Rainbow City of China Resources
- NO.68, Qinghe Middle Street Haidian District, Beijing 100085
- CN
-
-DC-BF-E9 (hex) Motorola Mobility LLC, a Lenovo Company
-DCBFE9 (base 16) Motorola Mobility LLC, a Lenovo Company
- 222 West Merchandise Mart Plaza
- Chicago IL 60654
- US
-
-2C-37-C5 (hex) Qingdao Haier Intelligent Home Appliance Technology Co.,Ltd
-2C37C5 (base 16) Qingdao Haier Intelligent Home Appliance Technology Co.,Ltd
- ingdao high-tech park haier road 1
- Qingdao Shandong 266101
- CN
-
-74-95-EC (hex) ALPS ELECTRIC CO.,LTD.
-7495EC (base 16) ALPS ELECTRIC CO.,LTD.
- 6-1
- Kakuda Miyagi-Pref 981-1595
- JP
-
-18-52-82 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-185282 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan Hubei 430074
- CN
-
-18-D2-25 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-18D225 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan Hubei 430074
- CN
-
-04-02-CA (hex) Shenzhen Vtsonic Co.,ltd
-0402CA (base 16) Shenzhen Vtsonic Co.,ltd
- No.35,the 2nd Industrial Zone,Tangxiayong Village,Songgang Town,Bao'an District,Shenzhen,China.
- Shenzhen Guangdong 518102
- CN
-
-30-6A-85 (hex) Samsung Electronics Co.,Ltd
-306A85 (base 16) Samsung Electronics Co.,Ltd
- #94-1, Imsoo-Dong
- Gumi Gyeongbuk 730-350
- KR
-
-E4-F1-4C (hex) Private
-E4F14C (base 16) Private
-
-34-1A-35 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-341A35 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan Hubei 430074
- CN
-
-6C-A8-58 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-6CA858 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan Hubei 430074
- CN
-
-74-CC-39 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-74CC39 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan Hubei 430074
- CN
-
-FC-F6-47 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-FCF647 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan City Hubei Province 430074
- CN
-
-10-88-CE (hex) Fiberhome Telecommunication Technologies Co.,LTD
-1088CE (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan City Hubei Province 430074
- CN
-
-BC-98-89 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-BC9889 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan City Hubei Province 430074
- CN
-
-E4-2F-26 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-E42F26 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan City Hubei Province 430074
- CN
-
-34-4B-3D (hex) Fiberhome Telecommunication Technologies Co.,LTD
-344B3D (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan City Hubei Province 430074
- CN
-
-70-B9-21 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-70B921 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan Hubei 430074
- CN
-
-74-E1-9A (hex) Fiberhome Telecommunication Technologies Co.,LTD
-74E19A (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan Hubei 430074
- CN
-
-94-8D-EF (hex) Oetiker Schweiz AG
-948DEF (base 16) Oetiker Schweiz AG
- Spätzstrasse 11
- Horgen 8810
- CH
-
-74-72-1E (hex) Edison Labs Inc.
-74721E (base 16) Edison Labs Inc.
- 1122 Stanyan St
- San Francisco CA 94117
- US
-
-A8-36-7A (hex) frogblue TECHNOLOGY GmbH
-A8367A (base 16) frogblue TECHNOLOGY GmbH
- Luxemburger Straße 6
- Kaiserslautern Rheinland-Pfalz 67657
- DE
-
-14-4E-34 (hex) Remote Solution
-144E34 (base 16) Remote Solution
- 92, Chogokri, Nammyun
- Kimcheon city Kyungbuk 740-871
- KR
-
-EC-65-CC (hex) Panasonic Automotive Systems Company of America
-EC65CC (base 16) Panasonic Automotive Systems Company of America
- 776 Highway 74 South
- Peachtree City 30269
- US
-
-DC-4E-F4 (hex) Shenzhen MTN Electronics CO., Ltd
-DC4EF4 (base 16) Shenzhen MTN Electronics CO., Ltd
- MTN Industrial Park, No. 5, 9 South Futai Road, Pingxi Community, Pingdi Street, Longgang District
- Shenzhen Guangdong 518117
- CN
-
-40-CD-7A (hex) Qingdao Hisense Communications Co.,Ltd.
-40CD7A (base 16) Qingdao Hisense Communications Co.,Ltd.
- Qianwangang Road 218
- Qingdao Shandong 266510
- CN
-
-7C-A1-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD
-7CA177 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
- No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
- Dongguan 523808
- CN
-
-E4-0E-EE (hex) HUAWEI TECHNOLOGIES CO.,LTD
-E40EEE (base 16) HUAWEI TECHNOLOGIES CO.,LTD
- No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
- Dongguan 523808
- CN
-
-20-47-DA (hex) Xiaomi Communications Co Ltd
-2047DA (base 16) Xiaomi Communications Co Ltd
- The Rainbow City of China Resources
- NO.68, Qinghe Middle Street Haidian District, Beijing 100085
- CN
-
-10-1D-51 (hex) 8Mesh Networks Limited
-101D51 (base 16) 8Mesh Networks Limited
- Unit 607, 6/F, Yen Sheng Centre,
- 64 Hoi Yuen Road Kwun Tong 000
- HK
-
-80-35-C1 (hex) Xiaomi Communications Co Ltd
-8035C1 (base 16) Xiaomi Communications Co Ltd
- The Rainbow City of China Resources
- NO.68, Qinghe Middle Street Haidian District, Beijing 100085
- CN
-
-78-B6-EC (hex) Scuf Gaming International LLC
-78B6EC (base 16) Scuf Gaming International LLC
- 3970 Johns Creek Court Suite 325 Suwanee
- Atlanta GA 30024
- US
-
-00-25-D4 (hex) General Dynamics Mission Systems
-0025D4 (base 16) General Dynamics Mission Systems
- 150 Rustcraft Road
- Dedham MA 02026
- US
-
-D0-76-E7 (hex) TP-LINK TECHNOLOGIES CO.,LTD.
-D076E7 (base 16) TP-LINK TECHNOLOGIES CO.,LTD.
- Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan
- Shenzhen Guangdong 518057
- CN
-
-DC-29-19 (hex) AltoBeam (Xiamen) Technology Ltd, Co.
-DC2919 (base 16) AltoBeam (Xiamen) Technology Ltd, Co.
- South Building 203-38,Huoju Square ,No.56-58,Huoju Road, Huoju Park, Huoju High-tech District
- Xiamen 361000
- CN
-
-00-58-3F (hex) PC Aquarius
-00583F (base 16) PC Aquarius
- Comcity Office Park, Kievskoe shosse, est.6, bld. 1, Rumyantsevo, Moscow, 108811, RF
- Moscow 108811
- RU
-
-F0-9C-D7 (hex) Guangzhou Blue Cheetah Intelligent Technology Co., Ltd.
-F09CD7 (base 16) Guangzhou Blue Cheetah Intelligent Technology Co., Ltd.
- Panyu District, Guangzhou City Panyu Avenue North 555 Panyu Energy Technology Park,Industry Building 2 seats 406-407
- Guangzhou Guangdong 511400
- CN
-
-00-20-0E (hex) NSSLGlobal Technologies AS
-00200E (base 16) NSSLGlobal Technologies AS
- Martin Linges vei 25
- Fornebu 1364
- NO
-
-E0-38-3F (hex) zte corporation
-E0383F (base 16) zte corporation
- 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
- shenzhen guangdong 518057
- CN
-
-00-25-0C (hex) Senet Inc
-00250C (base 16) Senet Inc
- 100 Market Street, Suite 302
- Portsmouth NH 03801
- US
-
-DC-33-0D (hex) QING DAO HAIER TELECOM CO.,LTD.
-DC330D (base 16) QING DAO HAIER TELECOM CO.,LTD.
- No 1 Haier road,Hi-tech Zone,Qingdao,PR.China
- Qingdao Shandong 266101
- CN
-
-E8-3E-FC (hex) ARRIS Group, Inc.
-E83EFC (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-E8-89-2C (hex) ARRIS Group, Inc.
-E8892C (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-00-1D-D3 (hex) ARRIS Group, Inc.
-001DD3 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-00-15-D1 (hex) ARRIS Group, Inc.
-0015D1 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-3C-DF-A9 (hex) ARRIS Group, Inc.
-3CDFA9 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-8C-09-F4 (hex) ARRIS Group, Inc.
-8C09F4 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-08-3E-0C (hex) ARRIS Group, Inc.
-083E0C (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-44-6A-B7 (hex) ARRIS Group, Inc.
-446AB7 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-D4-04-CD (hex) ARRIS Group, Inc.
-D404CD (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-10-56-11 (hex) ARRIS Group, Inc.
-105611 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-2C-99-24 (hex) ARRIS Group, Inc.
-2C9924 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-64-55-B1 (hex) ARRIS Group, Inc.
-6455B1 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-C0-05-C2 (hex) ARRIS Group, Inc.
-C005C2 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-20-3D-66 (hex) ARRIS Group, Inc.
-203D66 (base 16) ARRIS Group, Inc.
- 6450 Sequence Drive
- San Diego CA 92121
- US
-
-40-F0-4E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
-40F04E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
- Phase 3, Bayan Lepas FIZ
- Bayan Lepas Penang 11900
- MY
-
-58-DB-15 (hex) TECNO MOBILE LIMITED
-58DB15 (base 16) TECNO MOBILE LIMITED
- ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG
- Hong Kong Hong Kong 999077
- HK
-
-44-66-FC (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
-4466FC (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
- NO.18 HAIBIN ROAD,
- DONG GUAN GUANG DONG 523860
- CN
-
-38-35-FB (hex) Sagemcom Broadband SAS
-3835FB (base 16) Sagemcom Broadband SAS
- 250, route de l'Empereur
- Rueil Malmaison Cedex hauts de seine 92848
- FR
-
-00-00-A8 (hex) Stratus Technologies
-0000A8 (base 16) Stratus Technologies
- 5 Mill and Main Place, Suite 500
- Maynard MA 01754
- US
-
-00-04-FC (hex) Stratus Technologies
-0004FC (base 16) Stratus Technologies
- 5 Mill and Main Place, Suite 500
- Maynard MA 01754
- US
-
-00-CB-B4 (hex) SHENZHEN ATEKO PHOTOELECTRICITY CO.,LTD
-00CBB4 (base 16) SHENZHEN ATEKO PHOTOELECTRICITY CO.,LTD
- 4-5F,E1 Building,TCL International E City,No.1001 Zhongshanyuan Road,Nanshan District,Shenzhen
- SHENZHEN GUANGDONG 518052
- CN
-
-70-79-B3 (hex) Cisco Systems, Inc
-7079B3 (base 16) Cisco Systems, Inc
- 80 West Tasman Drive
- San Jose CA 94568
- US
-
-0C-B3-4F (hex) Shenzhen Xiaoqi Intelligent Technology Co., Ltd.
-0CB34F (base 16) Shenzhen Xiaoqi Intelligent Technology Co., Ltd.
- Room 1501, Block B4, Building 9, Section 2, Shenzhen Bay Science & Technology Ecological Park, West Shahe Road, Nanshan District,
- Shenzhen Guangdong 518000
- CN
-
-F0-4C-D5 (hex) Maxlinear, Inc
-F04CD5 (base 16) Maxlinear, Inc
- 5966 La Place Ct. Ste# 100
- Carlsbad CA 92008
- US
-
-BC-99-11 (hex) Zyxel Communications Corporation
-BC9911 (base 16) Zyxel Communications Corporation
- No. 6 Innovation Road II, Science Park
- Hsichu Taiwan 300
- TW
-
-28-02-45 (hex) Konze System Technology Co.,Ltd.
-280245 (base 16) Konze System Technology Co.,Ltd.
- 4F., No.134, Ln. 235, Baoqiao Rd., Xindian Dist.
- New Taipei City --- 231
- TW
-
-8C-1C-DA (hex) IEEE Registration Authority
-8C1CDA (base 16) IEEE Registration Authority
- 445 Hoes Lane
- Piscataway NJ 08554
- US
-
-E8-D0-99 (hex) Fiberhome Telecommunication Technologies Co.,LTD
-E8D099 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
- No.5 DongXin Road
- Wuhan Hubei 430074
- CN
-
-D0-B2-14 (hex) PoeWit Inc
-D0B214 (base 16) PoeWit Inc
- 2307 Sea Island Dr
- Fort Lauderdale FL 33301
- US
-
-08-47-D0 (hex) Nokia Shanghai Bell Co. Ltd.)
-0847D0 (base 16) Nokia Shanghai Bell Co. Ltd.)
- No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai 201206,P.R.China
- Shanghai Pudong 201206
- CN
-
-18-69-DA (hex) China Mobile Group Device Co.,Ltd.
-1869DA (base 16) China Mobile Group Device Co.,Ltd.
- 32 Xuanwumen West Street,Xicheng District
- Beijing 100053
- CN
-
-60-D2-1C (hex) Sunnovo International Limited
-60D21C (base 16) Sunnovo International Limited
- 1717 Haitai Building
- Beijing Beijing 100083
- CN
-
-A4-92-CB (hex) Nokia
-A492CB (base 16) Nokia
- 600 March Road
- Kanata Ontario K2K 2E6
- CA
-
-DC-B4-AC (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
-DCB4AC (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
- Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC
- Zhuhai Guangdong 519180
- CN
-
-5C-CD-7C (hex) MEIZU Technology Co.,Ltd.
-5CCD7C (base 16) MEIZU Technology Co.,Ltd.
- MEIZU Tech Bldg., Technology& Innovation Coast
- Zhuhai Guangdong 519085
- CN
-
-A8-7D-12 (hex) HUAWEI TECHNOLOGIES CO.,LTD
-A87D12 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
- No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
- Dongguan 523808
- CN
-
-C0-F4-E6 (hex) HUAWEI TECHNOLOGIES CO.,LTD
-C0F4E6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
- No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
- Dongguan 523808
- CN
-
-2C-48-35 (hex) IEEE Registration Authority
-2C4835 (base 16) IEEE Registration Authority
- 445 Hoes Lane
- Piscataway NJ 08554
- US
-
-D4-60-E3 (hex) Sercomm Corporation.
-D460E3 (base 16) Sercomm Corporation.
- 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
- Miao-Lih Hsuan 115
- TW
-
-00-C0-02 (hex) Sercomm Corporation.
-00C002 (base 16) Sercomm Corporation.
- 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
- Miao-Lih Hsuan 115
- TW
-
-E0-60-66 (hex) Sercomm Corporation.
-E06066 (base 16) Sercomm Corporation.
- 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
- Miao-Lih Hsuan 115
- TW
-
-A4-15-66 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
-A41566 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
- Wei fang Export processing Zone
- Wei Fang Shan Dong 261205
- CN
-
-FC-A6-21 (hex) Samsung Electronics Co.,Ltd
-FCA621 (base 16) Samsung Electronics Co.,Ltd
- #94-1, Imsoo-Dong
- Gumi Gyeongbuk 730-350
- KR
-
-60-D0-2C (hex) Ruckus Wireless
-60D02C (base 16) Ruckus Wireless
- 350 West Java Drive
- Sunnyvale CA 94089
- US
-
-8C-F2-28 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
-8CF228 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
- Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan
- Shenzhen Guangdong 518057
- CN
-
-00-80-B6 (hex) Mercury Systems – Trusted Mission Solutions, Inc.
-0080B6 (base 16) Mercury Systems – Trusted Mission Solutions, Inc.
- 6681 OWENS DRIVE
- PLEASONTON CA 94588
- US
-
-C8-77-8B (hex) Mercury Systems – Trusted Mission Solutions, Inc.
-C8778B (base 16) Mercury Systems – Trusted Mission Solutions, Inc.
- 47200 Bayside Pkwy
- Fremont CA 94538
- US
-
-80-B3-2A (hex) UK Grid Solutions Ltd
-80B32A (base 16) UK Grid Solutions Ltd
- Harry Kerr Drive
- Stafford Staffordshire ST17 4LX
- GB
-
-00-09-DF (hex) Vestel Elektronik San ve Tic. A.Ş.
-0009DF (base 16) Vestel Elektronik San ve Tic. A.Ş.
- Organize san
- Manisa Turket 45030
- TR
-
-BC-5F-F6 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
-BC5FF6 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
- Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan
- Shenzhen Guangdong 518057
- CN
-
-9C-71-3A (hex) HUAWEI TECHNOLOGIES CO.,LTD
-9C713A (base 16) HUAWEI TECHNOLOGIES CO.,LTD
- No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
- Dongguan 523808
- CN
-
-B4-43-26 (hex) HUAWEI TECHNOLOGIES CO.,LTD
-B44326 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
- No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
- Dongguan 523808
- CN
-
-24-EC-51 (hex) ADF Technologies Sdn Bhd
-24EC51 (base 16) ADF Technologies Sdn Bhd
- Plot 88F, Lintang Bayan Lepas 10, Bayan Lepas Industrial Park Phase IV
- Bayan Lepas Pulau Pinang 11900
- MY
-
-38-56-B5 (hex) Peerbridge Health Inc
-3856B5 (base 16) Peerbridge Health Inc
- 3 Columbus Circle 15th Fl
- New York NY 10019
- US
-
AC-F8-5C (hex) Private
ACF85C (base 16) Private
@@ -88148,72 +87938,1665 @@ D82477 (base 16) Universal Electric Corporation
Dallas TX 75243
US
-30-A8-DB (hex) Sony Mobile Communications AB
-30A8DB (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+80-29-94 (hex) Technicolor CH USA Inc.
+802994 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+E0-88-5D (hex) Technicolor CH USA Inc.
+E0885D (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+44-32-C8 (hex) Technicolor CH USA Inc.
+4432C8 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+80-B2-34 (hex) Technicolor CH USA Inc.
+80B234 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+38-6E-88 (hex) zte corporation
+386E88 (base 16) zte corporation
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
+ shenzhen guangdong 518057
+ CN
+
+BC-C3-1B (hex) Kygo Life AS
+BCC31B (base 16) Kygo Life AS
+ Sjolyst Plass 3
+ Oslo 0278
+ NO
+
+FC-D6-BD (hex) Robert Bosch GmbH
+FCD6BD (base 16) Robert Bosch GmbH
+ AE-BE/EKE
+ Leonberg BW 71206
+ DE
+
+78-2D-7E (hex) TRENDnet, Inc.
+782D7E (base 16) TRENDnet, Inc.
+ 20675 Manhattan Place
+ Torrance CA 90501
+ US
+
+28-AD-3E (hex) Shenzhen TONG BO WEI Technology CO.,LTD
+28AD3E (base 16) Shenzhen TONG BO WEI Technology CO.,LTD
+ Longhua District, Dalang street Langkou community Huarong Road Peng Tengda Industrial Park 4 5 floor
+ SHENZHEN guangdong 518109
+ CN
+
+B0-6E-BF (hex) ASUSTek COMPUTER INC.
+B06EBF (base 16) ASUSTek COMPUTER INC.
+ 15,Li-Te Rd., Peitou, Taipei 112, Taiwan
+ Taipei Taiwan 112
+ TW
+
+48-BA-4E (hex) Hewlett Packard
+48BA4E (base 16) Hewlett Packard
+ 11445 Compaq Center Drive
+ Houston TX 77070
+ US
+
+FC-65-DE (hex) Amazon Technologies Inc.
+FC65DE (base 16) Amazon Technologies Inc.
+ P.O Box 8102
+ Reno NV 89507
+ US
+
+F0-92-B4 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD
+F092B4 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD
+ FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road,
+ Chengdu Sichuan 610000
+ CN
+
+70-7D-95 (hex) Shenzhen City LinwlanTechnology Co. Ltd.
+707D95 (base 16) Shenzhen City LinwlanTechnology Co. Ltd.
+ 106 village road , manhole street Baoan district .
+ Shenzhen Guangdong 518125
+ CN
+
+28-D9-3E (hex) Telecor Inc.
+28D93E (base 16) Telecor Inc.
+ 6205 Kestrel Road
+ Mississauga Ontario L5T 2A1
+ CA
+
+8C-0F-83 (hex) Angie Hospitality LLC
+8C0F83 (base 16) Angie Hospitality LLC
+ 12465 S Fort St, Ste 300
+ Draper UT 84020-9021
+ US
+
+00-50-FC (hex) Edimax Technology Co. Ltd.
+0050FC (base 16) Edimax Technology Co. Ltd.
+ No. 278, Xinhu 1st Road
+ Taipei City Neihu Dist 248
+ TW
+
+74-83-EF (hex) Arista Networks
+7483EF (base 16) Arista Networks
+ 5453 Great America Parkway
+ Santa Clara CA 95054
+ US
+
+00-1C-73 (hex) Arista Networks
+001C73 (base 16) Arista Networks
+ 5470 Great America Pkwy
+ Santa Clara California 95054
+ US
+
+38-AD-8E (hex) New H3C Technologies Co., Ltd
+38AD8E (base 16) New H3C Technologies Co., Ltd
+ 466 Changhe Road, Binjiang District
+ Hangzhou Zhejiang 310052
+ CN
+
+00-12-48 (hex) Dell EMC
+001248 (base 16) Dell EMC
+ 176 South Street
+ Hopkinton MA 01748
+ US
+
+00-01-44 (hex) Dell EMC
+000144 (base 16) Dell EMC
+ 228 South St.
+ Hopkinton MA 01748
+ US
+
+00-BF-61 (hex) Samsung Electronics Co.,Ltd
+00BF61 (base 16) Samsung Electronics Co.,Ltd
+ 129, Samsung-ro, Youngtongl-Gu
+ Suwon Gyeonggi-Do 16677
+ KR
+
+30-9F-FB (hex) Ardomus Networks Corporation
+309FFB (base 16) Ardomus Networks Corporation
+ 4F,No. 6 Innovation Road II, Hsinchu Science Park
+ Hsinchu 300
+ TW
+
+E4-BD-4B (hex) zte corporation
+E4BD4B (base 16) zte corporation
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
+ shenzhen guangdong 518057
+ CN
+
+6C-56-97 (hex) Amazon Technologies Inc.
+6C5697 (base 16) Amazon Technologies Inc.
+ P.O Box 8102
+ Reno NV 89507
+ US
+
+3C-A5-81 (hex) vivo Mobile Communication Co., Ltd.
+3CA581 (base 16) vivo Mobile Communication Co., Ltd.
+ #283,BBK Road
+ Wusha,Chang'An DongGuan City,Guangdong, 523860
+ CN
+
+F4-EA-B5 (hex) Aerohive Networks Inc.
+F4EAB5 (base 16) Aerohive Networks Inc.
+ 1011 McCarthy Blvd
+ Milpitas CA 95035
+ US
+
+F8-20-55 (hex) Green Information System
+F82055 (base 16) Green Information System
+ #202(Shopping center), Woldong-ro 28, Buk-gu
+ Gwangju 61153
+ KR
+
+78-5C-28 (hex) Prime Motion Inc.
+785C28 (base 16) Prime Motion Inc.
+ Akaho 1134-12
+ Komagane Nagano 399-4117
+ JP
+
+94-49-96 (hex) WiSilica Inc
+944996 (base 16) WiSilica Inc
+ 23282 Mill Creek Dr #340
+ Laguna Hills CA 92653
+ US
+
+00-26-A8 (hex) DAEHAP HYPER-TECH
+0026A8 (base 16) DAEHAP HYPER-TECH
+ Mega center #1108, SK Techno-Park, #190-1, Sangdaewon-Dong, Jungwon-Gu
+ Seongnam Gyeonggi-Do 462-807
+ KR
+
+F8-7B-20 (hex) Cisco Systems, Inc
+F87B20 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+F8-1D-0F (hex) Hitron Technologies. Inc
+F81D0F (base 16) Hitron Technologies. Inc
+ No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C
+ Hsin-chu Taiwan 300
+ TW
+
+30-FB-94 (hex) Shanghai Fangzhiwei Information Technology CO.,Ltd.
+30FB94 (base 16) Shanghai Fangzhiwei Information Technology CO.,Ltd.
+ The 17th Building A Unit,No. 1688 Lianhang Road,Minhang District,Shanghai City
+ Shanghai 201100
+ CN
+
+08-BA-22 (hex) Swaive Corporation
+08BA22 (base 16) Swaive Corporation
+ 3565 Kettmann Road
+ San Jose CA 95121
+ US
+
+F8-0C-F3 (hex) LG Electronics (Mobile Communications)
+F80CF3 (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+30-76-6F (hex) LG Electronics (Mobile Communications)
+30766F (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+8C-3A-E3 (hex) LG Electronics (Mobile Communications)
+8C3AE3 (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+94-2A-3F (hex) Diversey Inc
+942A3F (base 16) Diversey Inc
+ 2415 Cascade Pointe Blvd
+ Charlotte NC 28208
+ US
+
+78-F8-82 (hex) LG Electronics (Mobile Communications)
+78F882 (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+0C-61-11 (hex) Anda Technologies SAC
+0C6111 (base 16) Anda Technologies SAC
+ Av. Santa Cruz 888, Miraflores
+ Lima Peru Lima18
+ PE
+
+B8-F7-4A (hex) RCNTEC
+B8F74A (base 16) RCNTEC
+ Polkovaya street 3
+ Moscow 127018
+ RU
+
+C8-D1-2A (hex) Comtrend Corporation
+C8D12A (base 16) Comtrend Corporation
+ 3F-1, No. 10, Lane 609, Chung Hsin Road, Sec 5, San Chung Dist.
+ New Taipei City Taiwan 24159
+ TW
+
+B4-F1-DA (hex) LG Electronics (Mobile Communications)
+B4F1DA (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+00-21-FB (hex) LG Electronics (Mobile Communications)
+0021FB (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+D0-13-FD (hex) LG Electronics (Mobile Communications)
+D013FD (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+A8-B8-6E (hex) LG Electronics (Mobile Communications)
+A8B86E (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+DC-4F-22 (hex) Espressif Inc.
+DC4F22 (base 16) Espressif Inc.
+ Room 204, Building 2, 690 Bibo Road, Pudong New Area
+ Shanghai Shanghai 201203
+ CN
+
+34-2A-F1 (hex) Texas Instruments
+342AF1 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+70-E5-6E (hex) Texas Instruments
+70E56E (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+F0-85-C1 (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
+F085C1 (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
+ Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District,
+ Shenzhen Guangdong 518000
+ CN
+
+C8-DE-C9 (hex) Coriant
+C8DEC9 (base 16) Coriant
+ 1415 W. Diehl Rd
+ Naperville IL 60563
+ US
+
+38-0E-4D (hex) Cisco Systems, Inc
+380E4D (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+FC-9D-D8 (hex) Beijing TongTongYiLian Science and Technology Ltd.
+FC9DD8 (base 16) Beijing TongTongYiLian Science and Technology Ltd.
+ Room 301,Zone 3,Building 9,No.8 Dongbeiwang West Road,Haidian District,Beijing
+ BEIJING BEIJING 100193
+ CN
+
+04-B1-67 (hex) Xiaomi Communications Co Ltd
+04B167 (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+38-AD-BE (hex) New H3C Technologies Co., Ltd
+38ADBE (base 16) New H3C Technologies Co., Ltd
+ 466 Changhe Road, Binjiang District
+ Hangzhou Zhejiang 310052
+ CN
+
+20-78-52 (hex) Nokia
+207852 (base 16) Nokia
+ Karaportti 3
+ Espoo Finland 02610
+ FI
+
+CC-5D-4E (hex) Zyxel Communications Corporation
+CC5D4E (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+40-4A-03 (hex) Zyxel Communications Corporation
+404A03 (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+00-13-49 (hex) Zyxel Communications Corporation
+001349 (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+1C-74-0D (hex) Zyxel Communications Corporation
+1C740D (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+A0-E4-CB (hex) Zyxel Communications Corporation
+A0E4CB (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+5C-6A-80 (hex) Zyxel Communications Corporation
+5C6A80 (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+5C-E2-8C (hex) Zyxel Communications Corporation
+5CE28C (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+A8-EE-C6 (hex) Muuselabs NV/SA
+A8EEC6 (base 16) Muuselabs NV/SA
+ Rue du Tocsin 12
+ Brussels 1000
+ BE
+
+A0-9D-C1 (hex) China Dragon Technology Limited
+A09DC1 (base 16) China Dragon Technology Limited
+ B4 Bldg.Haoshan 1st Industry Park,
+ Shenzhen Guangdong 518104
+ CN
+
+38-43-7D (hex) Compal Broadband Networks, Inc.
+38437D (base 16) Compal Broadband Networks, Inc.
+ 13F., No.1, Taiyuan 1st St.
+ Zhubei City Hsinchu County 30265
+ TW
+
+5C-86-C1 (hex) DONGGUAN SOLUM ELECTRONICS CO.,LTD
+5C86C1 (base 16) DONGGUAN SOLUM ELECTRONICS CO.,LTD
+ NO.157,13 Coastal Way TPFTZ
+ TIANJIN 300461
+ CN
+
+6C-DD-30 (hex) Cisco Systems, Inc
+6CDD30 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+00-80-6C (hex) Secure Systems & Services
+00806C (base 16) Secure Systems & Services
+ 24, Chemin de la Pouranque
+ F-13752 LES PENNES MIRABEAU CS30084
+ FR
+
+00-02-61 (hex) Tilgin AB
+000261 (base 16) Tilgin AB
+ Finlandsgatan 40
+
+ SE
+
+AC-E2-D3 (hex) Hewlett Packard
+ACE2D3 (base 16) Hewlett Packard
+ 11445 Compaq Center Drive
+ Houston TX 77070
+ US
+
+28-2F-C2 (hex) Automotive Data Solutions
+282FC2 (base 16) Automotive Data Solutions
+ 8400 rue Bougainville
+ Montreal Quebec H4P2G1
+ CA
+
+00-1D-38 (hex) Seagate Technology
+001D38 (base 16) Seagate Technology
+ M/S NW1F01
+ Longmont CO 80503
+ US
+
+68-3E-02 (hex) SIEMENS AG, Digital Factory, Motion Control System
+683E02 (base 16) SIEMENS AG, Digital Factory, Motion Control System
+ Varey Road
+ Congleton Cheshire CW12 1PH
+ GB
+
+34-E3-80 (hex) Genexis B.V.
+34E380 (base 16) Genexis B.V.
+ Lodewijkstraat 1A
+ Eindhoven 5652AC
+ NL
+
+2C-B2-1A (hex) Phicomm (Shanghai) Co., Ltd.
+2CB21A (base 16) Phicomm (Shanghai) Co., Ltd.
+ 3666 SiXian Rd.,Songjiang District
+ Shanghai Shanghai 201616
+ CN
+
+CC-81-DA (hex) Phicomm (Shanghai) Co., Ltd.
+CC81DA (base 16) Phicomm (Shanghai) Co., Ltd.
+ 3666 SiXian Rd.,Songjiang District
+ Shanghai Shanghai 201616
+ CN
+
+B8-07-16 (hex) vivo Mobile Communication Co., Ltd.
+B80716 (base 16) vivo Mobile Communication Co., Ltd.
+ #283,BBK Road
+ Wusha,Chang'An DongGuan City,Guangdong, 523860
+ CN
+
+C8-DF-84 (hex) Texas Instruments
+C8DF84 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+5C-0E-8B (hex) Extreme Networks, Inc.
+5C0E8B (base 16) Extreme Networks, Inc.
+ 475 Half Day Road
+ Lincolnshire IL 60069
+ US
+
+B4-C7-99 (hex) Extreme Networks, Inc.
+B4C799 (base 16) Extreme Networks, Inc.
+ 475 Half Day Road
+ Lincolnshire IL 60069
+ US
+
+74-67-F7 (hex) Extreme Networks, Inc.
+7467F7 (base 16) Extreme Networks, Inc.
+ 1 Zebra Plaza
+ Holtsville NY 11742
+ US
+
+98-00-74 (hex) Raisecom Technology CO., LTD
+980074 (base 16) Raisecom Technology CO., LTD
+ No. 11, East Area, No. 10 Block, East Xibeiwang Road
+ Beijing 100094
+ CN
+
+18-C1-9D (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
+18C19D (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
+ Phase 3, Bayan Lepas FIZ
+ Bayan Lepas Penang 11900
+ MY
+
+00-E0-2B (hex) Extreme Networks, Inc.
+00E02B (base 16) Extreme Networks, Inc.
+ 10460 BANDLEY DRIVE
+ CUPERINT0 CA 95014
+ US
+
+A4-86-AE (hex) Quectel Wireless Solutions
+A486AE (base 16) Quectel Wireless Solutions
+ No.1801 Hongmei Road, Xuhui District
+ Shanghai 200233
+ CN
+
+70-26-05 (hex) SONY Visual Products Inc.
+702605 (base 16) SONY Visual Products Inc.
+ 2-10-1 Osaki
+ Shinagawa-ku Tokyo 141-8610
+ JP
+
+5C-5F-67 (hex) Intel Corporate
+5C5F67 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+7C-76-35 (hex) Intel Corporate
+7C7635 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+DC-48-B2 (hex) Baraja Pty. Ltd.
+DC48B2 (base 16) Baraja Pty. Ltd.
+ 36 Bradfield Road
+ West Lindfield NSW 2070
+ AU
+
+00-01-23 (hex) Schneider Electric Japan Holdings Ltd.
+000123 (base 16) Schneider Electric Japan Holdings Ltd.
+ Schneider Electric Osaka Building
+ 4-4-9 Kitahama Chuo-ku, Osaka 541-0041
+ JP
+
+D8-63-75 (hex) Xiaomi Communications Co Ltd
+D86375 (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+DC-BF-E9 (hex) Motorola Mobility LLC, a Lenovo Company
+DCBFE9 (base 16) Motorola Mobility LLC, a Lenovo Company
+ 222 West Merchandise Mart Plaza
+ Chicago IL 60654
+ US
+
+2C-37-C5 (hex) Qingdao Haier Intelligent Home Appliance Technology Co.,Ltd
+2C37C5 (base 16) Qingdao Haier Intelligent Home Appliance Technology Co.,Ltd
+ ingdao high-tech park haier road 1
+ Qingdao Shandong 266101
+ CN
+
+74-95-EC (hex) ALPS ELECTRIC CO.,LTD.
+7495EC (base 16) ALPS ELECTRIC CO.,LTD.
+ 6-1
+ Kakuda Miyagi-Pref 981-1595
+ JP
+
+18-52-82 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+185282 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+18-D2-25 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+18D225 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+04-02-CA (hex) Shenzhen Vtsonic Co.,ltd
+0402CA (base 16) Shenzhen Vtsonic Co.,ltd
+ No.35,the 2nd Industrial Zone,Tangxiayong Village,Songgang Town,Bao'an District,Shenzhen,China.
+ Shenzhen Guangdong 518102
+ CN
+
+30-6A-85 (hex) Samsung Electronics Co.,Ltd
+306A85 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+E4-F1-4C (hex) Private
+E4F14C (base 16) Private
+
+34-1A-35 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+341A35 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+6C-A8-58 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+6CA858 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+74-CC-39 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+74CC39 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+FC-F6-47 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+FCF647 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan City Hubei Province 430074
+ CN
+
+10-88-CE (hex) Fiberhome Telecommunication Technologies Co.,LTD
+1088CE (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan City Hubei Province 430074
+ CN
+
+BC-98-89 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+BC9889 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan City Hubei Province 430074
+ CN
+
+E4-2F-26 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+E42F26 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan City Hubei Province 430074
+ CN
+
+34-4B-3D (hex) Fiberhome Telecommunication Technologies Co.,LTD
+344B3D (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan City Hubei Province 430074
+ CN
+
+70-B9-21 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+70B921 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+74-E1-9A (hex) Fiberhome Telecommunication Technologies Co.,LTD
+74E19A (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+94-8D-EF (hex) Oetiker Schweiz AG
+948DEF (base 16) Oetiker Schweiz AG
+ Spätzstrasse 11
+ Horgen 8810
+ CH
+
+74-72-1E (hex) Edison Labs Inc.
+74721E (base 16) Edison Labs Inc.
+ 1122 Stanyan St
+ San Francisco CA 94117
+ US
+
+A8-36-7A (hex) frogblue TECHNOLOGY GmbH
+A8367A (base 16) frogblue TECHNOLOGY GmbH
+ Luxemburger Straße 6
+ Kaiserslautern Rheinland-Pfalz 67657
+ DE
+
+14-4E-34 (hex) Remote Solution
+144E34 (base 16) Remote Solution
+ 92, Chogokri, Nammyun
+ Kimcheon city Kyungbuk 740-871
+ KR
+
+EC-65-CC (hex) Panasonic Automotive Systems Company of America
+EC65CC (base 16) Panasonic Automotive Systems Company of America
+ 776 Highway 74 South
+ Peachtree City 30269
+ US
+
+DC-4E-F4 (hex) Shenzhen MTN Electronics CO., Ltd
+DC4EF4 (base 16) Shenzhen MTN Electronics CO., Ltd
+ MTN Industrial Park, No. 5, 9 South Futai Road, Pingxi Community, Pingdi Street, Longgang District
+ Shenzhen Guangdong 518117
+ CN
+
+40-CD-7A (hex) Qingdao Hisense Communications Co.,Ltd.
+40CD7A (base 16) Qingdao Hisense Communications Co.,Ltd.
+ Qianwangang Road 218
+ Qingdao Shandong 266510
+ CN
+
+7C-A1-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+7CA177 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+E4-0E-EE (hex) HUAWEI TECHNOLOGIES CO.,LTD
+E40EEE (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+20-47-DA (hex) Xiaomi Communications Co Ltd
+2047DA (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+10-1D-51 (hex) 8Mesh Networks Limited
+101D51 (base 16) 8Mesh Networks Limited
+ Unit 607, 6/F, Yen Sheng Centre,
+ 64 Hoi Yuen Road Kwun Tong 000
+ HK
+
+80-35-C1 (hex) Xiaomi Communications Co Ltd
+8035C1 (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+78-B6-EC (hex) Scuf Gaming International LLC
+78B6EC (base 16) Scuf Gaming International LLC
+ 3970 Johns Creek Court Suite 325 Suwanee
+ Atlanta GA 30024
+ US
+
+00-25-D4 (hex) General Dynamics Mission Systems
+0025D4 (base 16) General Dynamics Mission Systems
+ 150 Rustcraft Road
+ Dedham MA 02026
+ US
+
+D0-76-E7 (hex) TP-LINK TECHNOLOGIES CO.,LTD.
+D076E7 (base 16) TP-LINK TECHNOLOGIES CO.,LTD.
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan
+ Shenzhen Guangdong 518057
+ CN
+
+DC-29-19 (hex) AltoBeam (Xiamen) Technology Ltd, Co.
+DC2919 (base 16) AltoBeam (Xiamen) Technology Ltd, Co.
+ South Building 203-38,Huoju Square ,No.56-58,Huoju Road, Huoju Park, Huoju High-tech District
+ Xiamen 361000
+ CN
+
+00-58-3F (hex) PC Aquarius
+00583F (base 16) PC Aquarius
+ Comcity Office Park, Kievskoe shosse, est.6, bld. 1, Rumyantsevo, Moscow, 108811, RF
+ Moscow 108811
+ RU
+
+F0-9C-D7 (hex) Guangzhou Blue Cheetah Intelligent Technology Co., Ltd.
+F09CD7 (base 16) Guangzhou Blue Cheetah Intelligent Technology Co., Ltd.
+ Panyu District, Guangzhou City Panyu Avenue North 555 Panyu Energy Technology Park,Industry Building 2 seats 406-407
+ Guangzhou Guangdong 511400
+ CN
+
+00-20-0E (hex) NSSLGlobal Technologies AS
+00200E (base 16) NSSLGlobal Technologies AS
+ Martin Linges vei 25
+ Fornebu 1364
+ NO
+
+E0-38-3F (hex) zte corporation
+E0383F (base 16) zte corporation
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
+ shenzhen guangdong 518057
+ CN
+
+00-25-0C (hex) Senet Inc
+00250C (base 16) Senet Inc
+ 100 Market Street, Suite 302
+ Portsmouth NH 03801
+ US
+
+DC-33-0D (hex) QING DAO HAIER TELECOM CO.,LTD.
+DC330D (base 16) QING DAO HAIER TELECOM CO.,LTD.
+ No 1 Haier road,Hi-tech Zone,Qingdao,PR.China
+ Qingdao Shandong 266101
+ CN
+
+E8-3E-FC (hex) ARRIS Group, Inc.
+E83EFC (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+E8-89-2C (hex) ARRIS Group, Inc.
+E8892C (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+00-1D-D3 (hex) ARRIS Group, Inc.
+001DD3 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+00-15-D1 (hex) ARRIS Group, Inc.
+0015D1 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+3C-DF-A9 (hex) ARRIS Group, Inc.
+3CDFA9 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+8C-09-F4 (hex) ARRIS Group, Inc.
+8C09F4 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+08-3E-0C (hex) ARRIS Group, Inc.
+083E0C (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+44-6A-B7 (hex) ARRIS Group, Inc.
+446AB7 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+D4-04-CD (hex) ARRIS Group, Inc.
+D404CD (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+10-56-11 (hex) ARRIS Group, Inc.
+105611 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+2C-99-24 (hex) ARRIS Group, Inc.
+2C9924 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+64-55-B1 (hex) ARRIS Group, Inc.
+6455B1 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+C0-05-C2 (hex) ARRIS Group, Inc.
+C005C2 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+20-3D-66 (hex) ARRIS Group, Inc.
+203D66 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+40-F0-4E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
+40F04E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
+ Phase 3, Bayan Lepas FIZ
+ Bayan Lepas Penang 11900
+ MY
+
+58-DB-15 (hex) TECNO MOBILE LIMITED
+58DB15 (base 16) TECNO MOBILE LIMITED
+ ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG
+ Hong Kong Hong Kong 999077
+ HK
+
+44-66-FC (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+4466FC (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+ NO.18 HAIBIN ROAD,
+ DONG GUAN GUANG DONG 523860
+ CN
+
+38-35-FB (hex) Sagemcom Broadband SAS
+3835FB (base 16) Sagemcom Broadband SAS
+ 250, route de l'Empereur
+ Rueil Malmaison Cedex hauts de seine 92848
+ FR
+
+00-00-A8 (hex) Stratus Technologies
+0000A8 (base 16) Stratus Technologies
+ 5 Mill and Main Place, Suite 500
+ Maynard MA 01754
+ US
+
+00-04-FC (hex) Stratus Technologies
+0004FC (base 16) Stratus Technologies
+ 5 Mill and Main Place, Suite 500
+ Maynard MA 01754
+ US
+
+00-CB-B4 (hex) SHENZHEN ATEKO PHOTOELECTRICITY CO.,LTD
+00CBB4 (base 16) SHENZHEN ATEKO PHOTOELECTRICITY CO.,LTD
+ 4-5F,E1 Building,TCL International E City,No.1001 Zhongshanyuan Road,Nanshan District,Shenzhen
+ SHENZHEN GUANGDONG 518052
+ CN
+
+70-79-B3 (hex) Cisco Systems, Inc
+7079B3 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+0C-B3-4F (hex) Shenzhen Xiaoqi Intelligent Technology Co., Ltd.
+0CB34F (base 16) Shenzhen Xiaoqi Intelligent Technology Co., Ltd.
+ Room 1501, Block B4, Building 9, Section 2, Shenzhen Bay Science & Technology Ecological Park, West Shahe Road, Nanshan District,
+ Shenzhen Guangdong 518000
+ CN
+
+F0-4C-D5 (hex) Maxlinear, Inc
+F04CD5 (base 16) Maxlinear, Inc
+ 5966 La Place Ct. Ste# 100
+ Carlsbad CA 92008
+ US
+
+BC-99-11 (hex) Zyxel Communications Corporation
+BC9911 (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+28-02-45 (hex) Konze System Technology Co.,Ltd.
+280245 (base 16) Konze System Technology Co.,Ltd.
+ 4F., No.134, Ln. 235, Baoqiao Rd., Xindian Dist.
+ New Taipei City --- 231
+ TW
+
+8C-1C-DA (hex) IEEE Registration Authority
+8C1CDA (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+E8-D0-99 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+E8D099 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+D0-B2-14 (hex) PoeWit Inc
+D0B214 (base 16) PoeWit Inc
+ 2307 Sea Island Dr
+ Fort Lauderdale FL 33301
+ US
+
+08-47-D0 (hex) Nokia Shanghai Bell Co. Ltd.)
+0847D0 (base 16) Nokia Shanghai Bell Co. Ltd.)
+ No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai 201206,P.R.China
+ Shanghai Pudong 201206
+ CN
+
+18-69-DA (hex) China Mobile Group Device Co.,Ltd.
+1869DA (base 16) China Mobile Group Device Co.,Ltd.
+ 32 Xuanwumen West Street,Xicheng District
+ Beijing 100053
+ CN
+
+60-D2-1C (hex) Sunnovo International Limited
+60D21C (base 16) Sunnovo International Limited
+ 1717 Haitai Building
+ Beijing Beijing 100083
+ CN
+
+A4-92-CB (hex) Nokia
+A492CB (base 16) Nokia
+ 600 March Road
+ Kanata Ontario K2K 2E6
+ CA
+
+DC-B4-AC (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
+DCB4AC (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD.
+ Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC
+ Zhuhai Guangdong 519180
+ CN
+
+5C-CD-7C (hex) MEIZU Technology Co.,Ltd.
+5CCD7C (base 16) MEIZU Technology Co.,Ltd.
+ MEIZU Tech Bldg., Technology& Innovation Coast
+ Zhuhai Guangdong 519085
+ CN
+
+A8-7D-12 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+A87D12 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+C0-F4-E6 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+C0F4E6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+2C-48-35 (hex) IEEE Registration Authority
+2C4835 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+D4-60-E3 (hex) Sercomm Corporation.
+D460E3 (base 16) Sercomm Corporation.
+ 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
+ Miao-Lih Hsuan 115
+ TW
+
+00-C0-02 (hex) Sercomm Corporation.
+00C002 (base 16) Sercomm Corporation.
+ 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
+ Miao-Lih Hsuan 115
+ TW
+
+E0-60-66 (hex) Sercomm Corporation.
+E06066 (base 16) Sercomm Corporation.
+ 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen
+ Miao-Lih Hsuan 115
+ TW
+
+A4-15-66 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
+A41566 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
+ Wei fang Export processing Zone
+ Wei Fang Shan Dong 261205
+ CN
+
+FC-A6-21 (hex) Samsung Electronics Co.,Ltd
+FCA621 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+60-D0-2C (hex) Ruckus Wireless
+60D02C (base 16) Ruckus Wireless
+ 350 West Java Drive
+ Sunnyvale CA 94089
+ US
+
+8C-F2-28 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+8CF228 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+ Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan
+ Shenzhen Guangdong 518057
+ CN
+
+00-80-B6 (hex) Mercury Systems – Trusted Mission Solutions, Inc.
+0080B6 (base 16) Mercury Systems – Trusted Mission Solutions, Inc.
+ 6681 OWENS DRIVE
+ PLEASONTON CA 94588
+ US
+
+C8-77-8B (hex) Mercury Systems – Trusted Mission Solutions, Inc.
+C8778B (base 16) Mercury Systems – Trusted Mission Solutions, Inc.
+ 47200 Bayside Pkwy
+ Fremont CA 94538
+ US
+
+80-B3-2A (hex) UK Grid Solutions Ltd
+80B32A (base 16) UK Grid Solutions Ltd
+ Harry Kerr Drive
+ Stafford Staffordshire ST17 4LX
+ GB
+
+00-09-DF (hex) Vestel Elektronik San ve Tic. A.Ş.
+0009DF (base 16) Vestel Elektronik San ve Tic. A.Ş.
+ Organize san
+ Manisa Turket 45030
+ TR
+
+BC-5F-F6 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+BC5FF6 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+ Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan
+ Shenzhen Guangdong 518057
+ CN
+
+9C-71-3A (hex) HUAWEI TECHNOLOGIES CO.,LTD
+9C713A (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+B4-43-26 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+B44326 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+24-EC-51 (hex) ADF Technologies Sdn Bhd
+24EC51 (base 16) ADF Technologies Sdn Bhd
+ Plot 88F, Lintang Bayan Lepas 10, Bayan Lepas Industrial Park Phase IV
+ Bayan Lepas Pulau Pinang 11900
+ MY
+
+38-56-B5 (hex) Peerbridge Health Inc
+3856B5 (base 16) Peerbridge Health Inc
+ 3 Columbus Circle 15th Fl
+ New York NY 10019
+ US
+
+64-4F-42 (hex) JETTER CO., Ltd.
+644F42 (base 16) JETTER CO., Ltd.
+ 265-40 Emukaecho Tanomoto
+ Sasebo-shi Nagasaki 859-6134
+ JP
+
+14-CA-A0 (hex) Hu&Co
+14CAA0 (base 16) Hu&Co
+ 105 Rue du Jardin
+ Bordeaux 33000
+ FR
+
+30-A8-DB (hex) Sony Mobile Communications Inc
+30A8DB (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-44-74-6C (hex) Sony Mobile Communications AB
-44746C (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+44-74-6C (hex) Sony Mobile Communications Inc
+44746C (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-18-00-2D (hex) Sony Mobile Communications AB
-18002D (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+18-00-2D (hex) Sony Mobile Communications Inc
+18002D (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-30-17-C8 (hex) Sony Mobile Communications AB
-3017C8 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+30-17-C8 (hex) Sony Mobile Communications Inc
+3017C8 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-23-F1 (hex) Sony Mobile Communications AB
-0023F1 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-60-BD (hex) Enginuity Communications
+0060BD (base 16) Enginuity Communications
+ 3545 Stern Avenue
+ St Charles IL 60174
+ US
+
+00-23-F1 (hex) Sony Mobile Communications Inc
+0023F1 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-1B-59 (hex) Sony Mobile Communications AB
-001B59 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-1B-59 (hex) Sony Mobile Communications Inc
+001B59 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-19-63 (hex) Sony Mobile Communications AB
-001963 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-19-63 (hex) Sony Mobile Communications Inc
+001963 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-1E-DC (hex) Sony Mobile Communications AB
-001EDC (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-1E-DC (hex) Sony Mobile Communications Inc
+001EDC (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-0F-DE (hex) Sony Mobile Communications AB
-000FDE (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-0F-DE (hex) Sony Mobile Communications Inc
+000FDE (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-0A-D9 (hex) Sony Mobile Communications AB
-000AD9 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+D0-EF-C1 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+D0EFC1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+64-6D-6C (hex) HUAWEI TECHNOLOGIES CO.,LTD
+646D6C (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+48-57-02 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+485702 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+00-0A-D9 (hex) Sony Mobile Communications Inc
+000AD9 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-64-4F-42 (hex) JETTER CO., Ltd.
-644F42 (base 16) JETTER CO., Ltd.
- 265-40 Emukaecho Tanomoto
- Sasebo-shi Nagasaki 859-6134
+9C-C9-50 (hex) Baumer Holding
+9CC950 (base 16) Baumer Holding
+ Hummelstrasse 17
+ Frauenfeld Thurgau 8501
+ CH
+
+B0-02-7E (hex) MULLER SERVICES
+B0027E (base 16) MULLER SERVICES
+ 107 Boulevard Ney
+ PARIS ILE DE FRANCE 75018
+ FR
+
+78-2F-17 (hex) Xlab Co.,Ltd
+782F17 (base 16) Xlab Co.,Ltd
+ #401 4F, Achasan-ro, Seongdong-gu
+ SEOUL 04793
+ KR
+
+C4-51-8D (hex) Shenzhen YOUHUA Technology Co., Ltd
+C4518D (base 16) Shenzhen YOUHUA Technology Co., Ltd
+ Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District
+ Shenzhen Guangdong 518055
+ CN
+
+78-DA-07 (hex) Zhejiang Tmall Technology Co., Ltd.
+78DA07 (base 16) Zhejiang Tmall Technology Co., Ltd.
+ Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District,
+ Shenzhen Guangdong 518000
+ CN
+
+00-13-A3 (hex) Siemens Home & Office Comm. Devices
+0013A3 (base 16) Siemens Home & Office Comm. Devices
+ 4849 Alpha Road
+ Dallas Texas 75244
+ US
+
+E0-73-5F (hex) NUCOM
+E0735F (base 16) NUCOM
+ Arte, 21,5B
+ Madrid Madrid 28033
+ ES
+
+B8-7C-6F (hex) NXP (China) Management Ltd.
+B87C6F (base 16) NXP (China) Management Ltd.
+ 21F, BM InterContinental Business Center, 100 Yu Tong Road
+ Shanghai Shanghai 200070
+ CN
+
+40-DC-9D (hex) HAJEN
+40DC9D (base 16) HAJEN
+ 102-1302, Sinwon-ro 88, Yeongtong-gu
+ Suwon-Si Gyeonggi-do 16681
+ KR
+
+A0-D6-35 (hex) WBS Technology
+A0D635 (base 16) WBS Technology
+ Unit32, 2 Slough Ave, Slough Business Park
+ Silverwater New South Wales 2128
+ AU
+
+84-B3-1B (hex) Kinexon GmbH
+84B31B (base 16) Kinexon GmbH
+ Schellingstrasse, 35
+ München 80799
+ DE
+
+14-48-02 (hex) THE YEOLRIM Co.,Ltd.
+144802 (base 16) THE YEOLRIM Co.,Ltd.
+ D-311,H Business Park,26,Beobwon-ro 9-gil Songpa-gu,Seoul Korea
+ Seoul 05836
+ KR
+
+EC-83-D5 (hex) GIRD Systems Inc
+EC83D5 (base 16) GIRD Systems Inc
+ 11260 Chester Road, Ste. 600
+ Cincinnati OH 45246
+ US
+
+0C-1C-57 (hex) Texas Instruments
+0C1C57 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+04-79-B7 (hex) Texas Instruments
+0479B7 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+00-23-5A (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+00235A (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO 25, The 3rd street,
+ KuanShan SUZHOU 215300
+ CN
+
+00-1B-38 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+001B38 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 25, THE 3RD AVENUE
+ KUNSHAN CITY SUZHOU PROVINCE 215300
+ CN
+
+00-BB-60 (hex) Intel Corporate
+00BB60 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+7C-6D-A6 (hex) Superwave Group LLC
+7C6DA6 (base 16) Superwave Group LLC
+ poselok Krasnaya Zarya, dom 15
+ Vsevolozhskiy raiyon Leningradskaya oblast 193149
+ RU
+
+A4-E6-15 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
+A4E615 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
+ Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China
+ SHENZHEN GUANGDONG 518057
+ CN
+
+08-D5-9D (hex) Sagemcom Broadband SAS
+08D59D (base 16) Sagemcom Broadband SAS
+ 250, route de l'Empereur
+ Rueil Malmaison Cedex hauts de seine 92848
+ FR
+
+AC-64-17 (hex) Siemens AG
+AC6417 (base 16) Siemens AG
+ Werner-von-Siemens Strasse 50
+ Amberg 92224
+ DE
+
+5C-26-23 (hex) WaveLynx Technologies Corporation
+5C2623 (base 16) WaveLynx Technologies Corporation
+ 100 Technology Drive, Building B, Ste 150
+ Broomfield CO 80021
+ US
+
+00-20-B5 (hex) YASKAWA ELECTRIC CORPORATION
+0020B5 (base 16) YASKAWA ELECTRIC CORPORATION
+ 2-1 Kurosakishiroishi, Yahatanishi-ku,
+ Kitakyushu 806-0004
JP
+30-D1-6B (hex) Liteon Technology Corporation
+30D16B (base 16) Liteon Technology Corporation
+ 4F, 90, Chien 1 Road
+ New Taipei City Taiwan 23585
+ TW
+
+0C-CB-85 (hex) Motorola Mobility LLC, a Lenovo Company
+0CCB85 (base 16) Motorola Mobility LLC, a Lenovo Company
+ 222 West Merchandise Mart Plaza
+ Chicago IL 60654
+ US
+
+0C-9D-92 (hex) ASUSTek COMPUTER INC.
+0C9D92 (base 16) ASUSTek COMPUTER INC.
+ 15,Li-Te Rd., Peitou, Taipei 112, Taiwan
+ Taipei Taiwan 112
+ TW
+
+80-A7-96 (hex) Neurotek LLC
+80A796 (base 16) Neurotek LLC
+ 3180 18th St, Ste 200
+ San Francisco CA 94110
+ US
+
+00-1B-84 (hex) Scan Engineering Telecom
+001B84 (base 16) Scan Engineering Telecom
+ Svobody str. 75
+ Voronezh 394030
+ RU
+
+0C-96-E6 (hex) Cloud Network Technology (Samoa) Limited
+0C96E6 (base 16) Cloud Network Technology (Samoa) Limited
+ Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District
+ Chongqing Chongqing 401332
+ CN
+
+88-35-C1 (hex) OI ELECTRIC CO.,LTD
+8835C1 (base 16) OI ELECTRIC CO.,LTD
+ 7-3-16 KIKUNA
+ YOKOHAMA KANAGAWA-KEN 222-0011
+ JP
+
+BC-F2-AF (hex) devolo AG
+BCF2AF (base 16) devolo AG
+ Charlottenburger Allee 67
+ Aachen NRW 52068
+ DE
+
+A4-D9-90 (hex) Samsung Electronics Co.,Ltd
+A4D990 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+5C-63-C9 (hex) Intellithings Ltd.
+5C63C9 (base 16) Intellithings Ltd.
+ Hanehoshet 10
+ Tel Aviv Israel 6971072
+ IL
+
+DC-F7-19 (hex) Cisco Systems, Inc
+DCF719 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+00-1E-80 (hex) Icotera A/S
+001E80 (base 16) Icotera A/S
+ Vibeholms Allé 16
+ Brøndby 2605
+ DK
+
+80-3A-F4 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+803AF4 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+48-A0-F8 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+48A0F8 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+94-A3-CA (hex) KonnectONE, LLC
+94A3CA (base 16) KonnectONE, LLC
+ 30 N Gould Street STE 4004
+ Sheridan WY 82801
+ US
+
+E0-0E-E1 (hex) We Corporation Inc.
+E00EE1 (base 16) We Corporation Inc.
+ 201, 33, Deokcheon-ro, Manan-gu
+ Anyang-si Gyeonggi-do 14088
+ KR
+
+34-2C-C4 (hex) Compal Broadband Networks, Inc.
+342CC4 (base 16) Compal Broadband Networks, Inc.
+ 13F., No.1, Taiyuan 1st St.
+ Zhubei City Hsinchu County 30265
+ TW
+
+48-A4-72 (hex) Intel Corporate
+48A472 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+F8-5E-3C (hex) SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD
+F85E3C (base 16) SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD
+ 4F,Bldg A2,Hedian Industrial Park,NO.8 Shijing Rd,Guanlan,Longhua District,ShenZhen,China
+ shengzhen 518110
+ CN
+
+7C-03-AB (hex) Xiaomi Communications Co Ltd
+7C03AB (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+C4-98-5C (hex) Hui Zhou Gaoshengda Technology Co.,LTD
+C4985C (base 16) Hui Zhou Gaoshengda Technology Co.,LTD
+ No.75,Zhongkai High-Tech Development District,Huizhou
+ Hui Zhou Guangdong 516006
+ CN
+
+E4-34-93 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+E43493 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+34-29-12 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+342912 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+B0-8B-CF (hex) Cisco Systems, Inc
+B08BCF (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+34-E5-EC (hex) Palo Alto Networks
+34E5EC (base 16) Palo Alto Networks
+ 3000 Tannery Way
+ Santa Clara CA 95054
+ US
+
+44-22-F1 (hex) S.FAC, INC
+4422F1 (base 16) S.FAC, INC
+ Bldg A203 Techno2 ro 187
+ Yuseong-Gu Daejeon 34025
+ KR
+
+18-AC-9E (hex) ITEL MOBILE LIMITED
+18AC9E (base 16) ITEL MOBILE LIMITED
+ RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K
+ Hong Kong KOWLOON 999077
+ HK
+
+A0-28-33 (hex) IEEE Registration Authority
+A02833 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+94-9B-2C (hex) Extreme Networks, Inc.
+949B2C (base 16) Extreme Networks, Inc.
+ 6480 Via Del Oro
+ San Jose 95119
+ US
+
+00-50-DA (hex) 3COM
+0050DA (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-10-4B (hex) 3COM
+00104B (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-60-08 (hex) 3COM
+006008 (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-A0-24 (hex) 3COM
+00A024 (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-60-8C (hex) 3COM
+00608C (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+7C-D3-0A (hex) INVENTEC CORPORATION
+7CD30A (base 16) INVENTEC CORPORATION
+ Inventec Building, 66 Hou-Kang Street
+ Taipei 111
+ TW
+
+00-1A-C5 (hex) Keysight Technologies, Inc.
+001AC5 (base 16) Keysight Technologies, Inc.
+ 1400 Fountaingrove Pkwy.
+ Santa Rosa CA 95403
+ US
+
+00-E0-5C (hex) PHC Corporation
+00E05C (base 16) PHC Corporation
+ 2-38-5 Nishishimbashi
+ Minato-ku Tokyo 105-8433
+ JP
+
+74-34-00 (hex) MTG Co., Ltd.
+743400 (base 16) MTG Co., Ltd.
+ MTG No. 2 HIKARI Bldg., 4-13 Honjindori
+ Nakamura-ku, Nagoya Aichi 453-0041
+ JP
+
+00-60-97 (hex) 3COM
+006097 (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+20-D8-0B (hex) Juniper Networks
+20D80B (base 16) Juniper Networks
+ 1133 Innovation Way
+ Sunnyvale CA 94089
+ US
+
+60-35-C0 (hex) SFR
+6035C0 (base 16) SFR
+ 12 rue jean-philippe Rameau CS 80001
+ La plaine saint denis FRANCE 93634
+ FR
+
+0C-7C-28 (hex) Nokia
+0C7C28 (base 16) Nokia
+ Karaportti 3
+ Espoo Finland 02610
+ FI
+
+FC-61-E9 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+FC61E9 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+D0-03-DF (hex) Samsung Electronics Co.,Ltd
+D003DF (base 16) Samsung Electronics Co.,Ltd
+ 129, Samsung-ro, Youngtongl-Gu
+ Suwon Gyeonggi-Do 16677
+ KR
+
+6C-C3-74 (hex) Texas Instruments
+6CC374 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+40-C8-1F (hex) Shenzhen Xinguodu Technology Co., Ltd.
+40C81F (base 16) Shenzhen Xinguodu Technology Co., Ltd.
+ F17A, JinSong Building, Tairan Industrial & Trade Park, Chegongmiao, Shennan Road,Futian District
+ Shenzhen Guangdong 518040
+ CN
+
+24-FC-E5 (hex) Samsung Electronics Co.,Ltd
+24FCE5 (base 16) Samsung Electronics Co.,Ltd
+ 129, Samsung-ro, Youngtongl-Gu
+ Suwon Gyeonggi-Do 16677
+ KR
+
+4C-1B-86 (hex) Arcadyan Corporation
+4C1B86 (base 16) Arcadyan Corporation
+ No.8, Sec.2, Guangfu Rd.
+ Hsinchu City Hsinchu 30071
+ TW
+
+18-56-80 (hex) Intel Corporate
+185680 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
D8-6C-E9 (hex) Sagemcom Broadband SAS
D86CE9 (base 16) Sagemcom Broadband SAS
250 route de l'Empereur
@@ -89522,12 +90905,6 @@ B49D0B (base 16) BQ
Bangalore Karnataka 560068
IN
-30-D3-2D (hex) devolo AG
-30D32D (base 16) devolo AG
- Charlottenburger Allee 60
- Aachen NRW 52068
- DE
-
CC-79-4A (hex) BLU Products Inc.
CC794A (base 16) BLU Products Inc.
Tower 4, Excellence Century Center
@@ -89888,12 +91265,6 @@ E48501 (base 16) Geberit International AG
Jona SG 8645
CH
-1C-39-47 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-1C3947 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
2C-AD-13 (hex) SHENZHEN ZHILU TECHNOLOGY CO.,LTD
2CAD13 (base 16) SHENZHEN ZHILU TECHNOLOGY CO.,LTD
B2-402 Kexin Science Park, Keyuan Road, Hi-tech Park, Nanshan District, Shenzhen
@@ -91178,12 +92549,6 @@ E0E631 (base 16) SNB TECHNOLOGIES LIMITED
Geretsried Bavarian 82538
DE
-94-C3-E4 (hex) SCA Schucker Gmbh & Co KG
-94C3E4 (base 16) SCA Schucker Gmbh & Co KG
- Gewerbestrasse 52
- Bretten 75015
- DE
-
FC-19-D0 (hex) Cloud Vision Networks Technology Co.,Ltd.
FC19D0 (base 16) Cloud Vision Networks Technology Co.,Ltd.
F/9,Hechuan Building 2016
@@ -99737,12 +101102,6 @@ EC3091 (base 16) Cisco Systems, Inc
Bedford Bedfordshire MK44 1LQ
GB
-00-18-49 (hex) Pigeon Point Systems LLC
-001849 (base 16) Pigeon Point Systems LLC
- 2191 S. El Camino Real
- Oceanside CA 95054
- US
-
00-17-C7 (hex) MARA Systems Consulting AB
0017C7 (base 16) MARA Systems Consulting AB
Instrumentvägen 45
@@ -99773,12 +101132,6 @@ EC3091 (base 16) Cisco Systems, Inc
Marietta Georgia 30068
US
-00-17-B6 (hex) Aquantia
-0017B6 (base 16) Aquantia
- 700 Tasman Dr.
- Milpitas CA 95035
- US
-
00-17-AF (hex) Enermet
0017AF (base 16) Enermet
Salvesenintie
@@ -101147,12 +102500,6 @@ EC3091 (base 16) Cisco Systems, Inc
Kita-ku Tokyo 115-0044
JP
-00-12-A5 (hex) Stargen, Inc.
-0012A5 (base 16) Stargen, Inc.
- 225 Cedar Hill Street
- Marlborough MA 01752
- US
-
00-12-AA (hex) IEE, Inc.
0012AA (base 16) IEE, Inc.
7740 Lemona Avenue
@@ -101309,12 +102656,6 @@ EC3091 (base 16) Cisco Systems, Inc
EU Normandie 76260
FR
-00-11-33 (hex) Siemens Austria SIMEA
-001133 (base 16) Siemens Austria SIMEA
- Siemensstrasse 90-92
- Vienna 1210
- AT
-
00-11-32 (hex) Synology Incorporated
001132 (base 16) Synology Incorporated
6F-2, No.106, Chang An W. Rd.,
@@ -101609,12 +102950,6 @@ EC3091 (base 16) Cisco Systems, Inc
Santa Barbara CA 93101
US
-00-0F-15 (hex) Kjaerulff1 A/S
-000F15 (base 16) Kjaerulff1 A/S
- C.F. Tietgens Boulevard 19
- Odense SØ Fyn 5220
- DK
-
00-0F-1A (hex) Gaming Support B.V.
000F1A (base 16) Gaming Support B.V.
Industrie weg 29
@@ -102743,12 +104078,6 @@ EC3091 (base 16) Cisco Systems, Inc
Hsin Chu 300
TW
-00-0C-8A (hex) Bose Corporation
-000C8A (base 16) Bose Corporation
- Automotive Systems Division (ASD)
- Stow MA 01775-9102
- US
-
00-0C-8F (hex) Nergal s.r.l.
000C8F (base 16) Nergal s.r.l.
Viale Bardanzellu,8
@@ -104432,12 +105761,6 @@ EC3091 (base 16) Cisco Systems, Inc
California MD 20619
US
-00-05-1A (hex) 3COM EUROPE LTD.
-00051A (base 16) 3COM EUROPE LTD.
- 3COM CENTRE
- UNITED KINGDOM
- GB
-
00-05-10 (hex) Infinite Shanghai Communication Terminals Ltd.
000510 (base 16) Infinite Shanghai Communication Terminals Ltd.
777 Chungiao Road, Pudong
@@ -105062,12 +106385,6 @@ EC3091 (base 16) Cisco Systems, Inc
Fremont CA 94538
US
-00-04-0B (hex) 3COM EUROPE LTD.
-00040B (base 16) 3COM EUROPE LTD.
- BOUNDARY WAY
- UNITED KINGDOM
- GB
-
00-04-04 (hex) Makino Milling Machine Co., Ltd.
000404 (base 16) Makino Milling Machine Co., Ltd.
4023 Nakatsu, Aikawa-machi
@@ -105092,12 +106409,6 @@ EC3091 (base 16) Cisco Systems, Inc
Santa Clara CA 95050
US
-00-04-76 (hex) 3 Com Corporation
-000476 (base 16) 3 Com Corporation
- 5400 Bayfront Plaza
- Santa Clara CA 95052
- US
-
00-04-69 (hex) Innocom, Inc.
000469 (base 16) Innocom, Inc.
655-2 Naebalsan-Dong
@@ -105458,12 +106769,6 @@ EC3091 (base 16) Cisco Systems, Inc
Shinagawa-ku, Tokyo 140-0002
JP
-00-01-21 (hex) Watchguard Technologies, Inc.
-000121 (base 16) Watchguard Technologies, Inc.
- 605 Fifth Ave. S
- Seattle WA 98104-3892
- US
-
00-01-28 (hex) EnjoyWeb, Inc.
000128 (base 16) EnjoyWeb, Inc.
3000 Scott Blvd. #107
@@ -105482,12 +106787,6 @@ EC3091 (base 16) Cisco Systems, Inc
Fremont CA 94538
US
-00-01-02 (hex) 3COM CORPORATION
-000102 (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-01-15 (hex) EXTRATECH CORPORATION
000115 (base 16) EXTRATECH CORPORATION
760 Thornton St., Unit 2
@@ -105914,12 +107213,6 @@ EC3091 (base 16) Cisco Systems, Inc
UNITED KINGDOM
GB
-00-01-49 (hex) T.D.T. Transfer Data Test GmbH
-000149 (base 16) T.D.T. Transfer Data Test GmbH
- Siemensstraße 18
-
- DE
-
00-D0-47 (hex) XN TECHNOLOGIES
00D047 (base 16) XN TECHNOLOGIES
P.O. BOX 350
@@ -106232,12 +107525,6 @@ EC3091 (base 16) Cisco Systems, Inc
San Jose CA 94568
US
-00-D0-D8 (hex) 3Com Corporation
-00D0D8 (base 16) 3Com Corporation
- 2133 LEGHORN STREET
- MOUNTAIN VIEW CA 94043
- US
-
00-D0-6B (hex) SR TELECOM INC.
00D06B (base 16) SR TELECOM INC.
8150 Trans Canada Highway
@@ -106964,12 +108251,6 @@ EC3091 (base 16) Cisco Systems, Inc
SO. SAN FRANCISCO CA 94080
US
-00-10-5A (hex) 3COM CORPORATION
-00105A (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-10-A9 (hex) ADHOC TECHNOLOGIES
0010A9 (base 16) ADHOC TECHNOLOGIES
1150 FIRST STREET
@@ -108719,12 +110000,6 @@ EC3091 (base 16) Cisco Systems, Inc
AU
-00-80-17 (hex) PFU LIMITED
-008017 (base 16) PFU LIMITED
- NETWORK SEC.
-
- JP
-
00-80-F8 (hex) MIZAR, INC.
0080F8 (base 16) MIZAR, INC.
1419 DUNN DRIVE
@@ -109559,12 +110834,6 @@ AA0003 (base 16) DIGITAL EQUIPMENT CORPORATION
Mayfield Heights OH 44124-6118
US
-00-00-C3 (hex) HARRIS CORP COMPUTER SYS DIV
-0000C3 (base 16) HARRIS CORP COMPUTER SYS DIV
- M/S 75
- MELBOURNE FL 32919
- US
-
00-00-04 (hex) XEROX CORPORATION
000004 (base 16) XEROX CORPORATION
M/S 105-50C
@@ -109655,12 +110924,6 @@ CC33BB (base 16) Sagemcom Broadband SAS
RUEIL MALMAISON CEDEX Hauts de Seine 92848
FR
-00-02-3F (hex) COMPAL ELECTRONICS, INC.
-00023F (base 16) COMPAL ELECTRONICS, INC.
- 581, Juikuang Rd.,
-
- TW
-
38-3B-C8 (hex) 2Wire Inc
383BC8 (base 16) 2Wire Inc
1764 Automation Parkway
@@ -110549,12 +111812,6 @@ A80600 (base 16) Samsung Electronics Co.,Ltd
Taipei Hsien 241
TW
-F4-06-8D (hex) devolo AG
-F4068D (base 16) devolo AG
- Charlottenburger Allee 60
- Aachen NRW 52068
- DE
-
00-0B-CA (hex) DATAVAN TC
000BCA (base 16) DATAVAN TC
4FL,#120-12,Chung Shan Rd, Sec.3
@@ -111107,12 +112364,6 @@ E42F56 (base 16) OptoMET GmbH
DE
-00-26-6C (hex) INVENTEC Corporation
-00266C (base 16) INVENTEC Corporation
- Inventec Building, 66 Hou-Kang Street Shih-Lin District,
- Taipei 111
- TW
-
00-1E-25 (hex) INTEK DIGITAL
001E25 (base 16) INTEK DIGITAL
1101, 11th Fl., Anyang K-center building, 1591-9
@@ -111575,36 +112826,6 @@ D8E0B8 (base 16) BULAT LLC
Hong kong 999077
CN
-CC-35-40 (hex) Technicolor CH USA Inc.
-CC3540 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-C4-27-95 (hex) Technicolor CH USA Inc.
-C42795 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-58-23-8C (hex) Technicolor CH USA Inc.
-58238C (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-70-5A-9E (hex) Technicolor CH USA Inc.
-705A9E (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-80-C6-AB (hex) Technicolor CH USA Inc.
-80C6AB (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
90-A4-DE (hex) Wistron Neweb Corporation
90A4DE (base 16) Wistron Neweb Corporation
20 Park Avenue II, Hsinchu Science Park,
@@ -113237,12 +114458,6 @@ B0958E (base 16) TP-LINK TECHNOLOGIES CO.,LTD.
Kulim Kedah 09000
MY
-20-A8-B9 (hex) Siemens
-20A8B9 (base 16) Siemens
- Oestliche Rheinbrueckenstrasse 50
- Karlsruhe Baden Wuerttemberg 76187
- DE
-
C8-1B-5C (hex) BCTech
C81B5C (base 16) BCTech
14 Building, Tiandeng road 259#
@@ -114383,18 +115598,6 @@ EC42B4 (base 16) ADC Corporation
Piscataway NJ 08554
US
-6C-F9-D2 (hex) Chengdu Goods for the Road Electronic Technology C
-6CF9D2 (base 16) Chengdu Goods for the Road Electronic Technology C
- High - West West West Center Road on the 4th
- Chengdu Sichuan 611731
- CN
-
-38-17-E1 (hex) Technicolor CH USA Inc.
-3817E1 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
64-16-66 (hex) Nest Labs Inc.
641666 (base 16) Nest Labs Inc.
3400 Hillview Ave.
@@ -114743,9 +115946,6 @@ D81FCC (base 16) Brocade Communications Systems, Inc.
San Jose CA 95134
US
-00-20-67 (hex) Private
-002067 (base 16) Private
-
00-60-DF (hex) Brocade Communications Systems, Inc.
0060DF (base 16) Brocade Communications Systems, Inc.
130 Holger Way
@@ -115178,12 +116378,6 @@ E8361D (base 16) Sense Labs, Inc.
Cambridge MA 02139
US
-A0-95-0C (hex) China Mobile IOTCompany Limited
-A0950C (base 16) China Mobile IOTCompany Limited
- No.8,Yuma Road, Chayuanxinqu
- Chongqing 401130
- CN
-
EC-F8-EB (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD
ECF8EB (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD
FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road,
@@ -115391,12 +116585,6 @@ D4AD2D (base 16) Fiberhome Telecommunication Technologies Co.,LTD
Hangzhou Zhejiang 310012
CN
-10-C2-5A (hex) Technicolor CH USA Inc.
-10C25A (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
8C-59-73 (hex) Zyxel Communications Corporation
8C5973 (base 16) Zyxel Communications Corporation
No. 6 Innovation Road II, Science Park
@@ -115421,12 +116609,6 @@ D4AD2D (base 16) Fiberhome Telecommunication Technologies Co.,LTD
San Jose CA 94568
US
-E4-2D-7B (hex) China Mobile IOT Company Limited
-E42D7B (base 16) China Mobile IOT Company Limited
- NO.8 Yu Ma Road, NanAn Area Chongqing,China
- Chongqing Chongqing 401336
- CN
-
04-EC-BB (hex) Fiberhome Telecommunication Technologies Co.,LTD
04ECBB (base 16) Fiberhome Telecommunication Technologies Co.,LTD
No.5 DongXin Road
@@ -116024,12 +117206,6 @@ D4FC13 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
Wuhan Hubei 430074
CN
-B0-53-65 (hex) China Mobile IOT Company Limited
-B05365 (base 16) China Mobile IOT Company Limited
- NO.8 Yu Ma Road, NanAn Area Chongqing,China
- Chongqing Chongqing 401336
- CN
-
1C-96-5A (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
1C965A (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China
@@ -116102,52 +117278,70 @@ A83E0E (base 16) HMD Global Oy
Arcugnano Vicenza 36057
IT
-E0-63-E5 (hex) Sony Mobile Communications AB
-E063E5 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
- Shinagawa-ku Tokyo 140-0002
- JP
-
-B4-52-7D (hex) Sony Mobile Communications AB
-B4527D (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
- Shinagawa-ku Tokyo 140-0002
- JP
-
08-D4-6A (hex) LG Electronics (Mobile Communications)
08D46A (base 16) LG Electronics (Mobile Communications)
60-39, Gasan-dong, Geumcheon-gu
Seoul 153-801
KR
-68-76-4F (hex) Sony Mobile Communications AB
-68764F (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
- Shinagawa-ku Tokyo 140-0002
+B4-EC-02 (hex) ALPS ELECTRIC CO.,LTD.
+B4EC02 (base 16) ALPS ELECTRIC CO.,LTD.
+ 6-1
+ Kakuda Miyagi-Pref 981-1595
JP
-58-48-22 (hex) Sony Mobile Communications AB
-584822 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-01-49 (hex) TDT AG
+000149 (base 16) TDT AG
+ Siemensstraße 18
+
+ DE
+
+A4-EA-8E (hex) Extreme Networks, Inc.
+A4EA8E (base 16) Extreme Networks, Inc.
+ 6480 Via Del Oro
+ San Jose CA 95119
+ US
+
+B8-85-84 (hex) Dell Inc.
+B88584 (base 16) Dell Inc.
+ One Dell Way
+ Round Rock TX 78682
+ US
+
+A4-26-18 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd.
+A42618 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd.
+ Phase 3, Bayan Lepas FIZ
+ Bayan Lepas Penang 11900
+ MY
+
+88-09-07 (hex) MKT Systemtechnik GmbH & Co. KG
+880907 (base 16) MKT Systemtechnik GmbH & Co. KG
+ Hasskampstraße 75-77
+ Bünde NRW 32257
+ DE
+
+E0-63-E5 (hex) Sony Mobile Communications Inc
+E063E5 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-6C-0E-0D (hex) Sony Mobile Communications AB
-6C0E0D (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+B4-52-7D (hex) Sony Mobile Communications Inc
+B4527D (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-24-EF (hex) Sony Mobile Communications AB
-0024EF (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+68-76-4F (hex) Sony Mobile Communications Inc
+68764F (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-B4-EC-02 (hex) ALPS ELECTRIC CO.,LTD.
-B4EC02 (base 16) ALPS ELECTRIC CO.,LTD.
- 6-1
- Kakuda Miyagi-Pref 981-1595
+58-48-22 (hex) Sony Mobile Communications Inc
+584822 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
+ Shinagawa-ku Tokyo 140-0002
JP
54-C5-7A (hex) Sunnovo International Limited
@@ -117668,48 +118862,723 @@ DCE305 (base 16) ZAO NPK Rotek
Moscow 129223
RU
-00-22-98 (hex) Sony Mobile Communications AB
-002298 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+C4-27-95 (hex) Technicolor CH USA Inc.
+C42795 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+CC-35-40 (hex) Technicolor CH USA Inc.
+CC3540 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+80-C6-AB (hex) Technicolor CH USA Inc.
+80C6AB (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+70-5A-9E (hex) Technicolor CH USA Inc.
+705A9E (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+38-17-E1 (hex) Technicolor CH USA Inc.
+3817E1 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+00-12-A5 (hex) Dolphin Interconnect Solutions AS
+0012A5 (base 16) Dolphin Interconnect Solutions AS
+ NILS Hansens Vei 13
+ Oslo 0667
+ NO
+
+58-23-8C (hex) Technicolor CH USA Inc.
+58238C (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+10-C2-5A (hex) Technicolor CH USA Inc.
+10C25A (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+24-D3-F2 (hex) zte corporation
+24D3F2 (base 16) zte corporation
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
+ shenzhen guangdong 518057
+ CN
+
+00-7E-95 (hex) Cisco Systems, Inc
+007E95 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+D4-7C-44 (hex) IEEE Registration Authority
+D47C44 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+6C-0E-0D (hex) Sony Mobile Communications Inc
+6C0E0D (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
+ Shinagawa-ku Tokyo 140-0002
+ JP
+
+00-24-EF (hex) Sony Mobile Communications Inc
+0024EF (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-1F-E4 (hex) Sony Mobile Communications AB
-001FE4 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-22-98 (hex) Sony Mobile Communications Inc
+002298 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-1D-28 (hex) Sony Mobile Communications AB
-001D28 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-1F-E4 (hex) Sony Mobile Communications Inc
+001FE4 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-16-B8 (hex) Sony Mobile Communications AB
-0016B8 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-1D-28 (hex) Sony Mobile Communications Inc
+001D28 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-1A-75 (hex) Sony Mobile Communications AB
-001A75 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-16-B8 (hex) Sony Mobile Communications Inc
+0016B8 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-0E-07 (hex) Sony Mobile Communications AB
-000E07 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-1A-75 (hex) Sony Mobile Communications Inc
+001A75 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-38-78-62 (hex) Sony Mobile Communications AB
-387862 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-0E-07 (hex) Sony Mobile Communications Inc
+000E07 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
+38-78-62 (hex) Sony Mobile Communications Inc
+387862 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
+ Shinagawa-ku Tokyo 140-0002
+ JP
+
+00-17-B6 (hex) Aquantia Corporation
+0017B6 (base 16) Aquantia Corporation
+ 700 Tasman Drive
+ Milpitas CA 95035
+ US
+
+00-80-17 (hex) PFU LIMITED
+008017 (base 16) PFU LIMITED
+ Nu 98-2 Unoke
+ Kahoku-shi, Ishikawa 929-1192
+ JP
+
+50-4C-7E (hex) THE 41ST INSTITUTE OF CETC
+504C7E (base 16) THE 41ST INSTITUTE OF CETC
+ No.98 Xiangjiang Road,Huangdao District,Qingdao,Shandong
+ Qingdao Shangdong 266555
+ CN
+
+40-EE-DD (hex) HUAWEI TECHNOLOGIES CO.,LTD
+40EEDD (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+84-8A-8D (hex) Cisco Systems, Inc
+848A8D (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+28-66-E3 (hex) AzureWave Technology Inc.
+2866E3 (base 16) AzureWave Technology Inc.
+ 8F., No. 94, Baozhong Rd.
+ New Taipei City Taiwan 231
+ TW
+
+00-0C-8A (hex) Bose Corporation
+000C8A (base 16) Bose Corporation
+ Automotive Systems Division (ASD)
+ Stow MA 01775-9102
+ US
+
+00-11-33 (hex) Siemens AG Austria
+001133 (base 16) Siemens AG Austria
+ Siemensstrasse 90-92
+ Vienna 1210
+ AT
+
+20-A8-B9 (hex) SIEMENS AG
+20A8B9 (base 16) SIEMENS AG
+ Oestliche Rheinbrueckenstrasse 50
+ Karlsruhe Baden Wuerttemberg 76187
+ DE
+
+34-80-0D (hex) Cavium Inc
+34800D (base 16) Cavium Inc
+ 15485 Sand Canyon Ave
+ Irvine CA 92618
+ US
+
+08-25-25 (hex) Xiaomi Communications Co Ltd
+082525 (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+F4-60-E2 (hex) Xiaomi Communications Co Ltd
+F460E2 (base 16) Xiaomi Communications Co Ltd
+ The Rainbow City of China Resources
+ NO.68, Qinghe Middle Street Haidian District, Beijing 100085
+ CN
+
+7C-9A-54 (hex) Technicolor CH USA Inc.
+7C9A54 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+88-97-65 (hex) exands
+889765 (base 16) exands
+ RM2202 , No. 666 Gubei road
+ shanghai 200336
+ CN
+
+00-51-ED (hex) LG Innotek
+0051ED (base 16) LG Innotek
+ 26, Hanamsandan 5beon-ro
+ Gwangju Gwangsan-gu 506-731
+ KR
+
+BC-30-D9 (hex) Arcadyan Corporation
+BC30D9 (base 16) Arcadyan Corporation
+ No.8, Sec.2, Guangfu Rd.
+ Hsinchu City Hsinchu 30071
+ TW
+
+3C-42-7E (hex) IEEE Registration Authority
+3C427E (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+F0-BC-C9 (hex) PFU LIMITED
+F0BCC9 (base 16) PFU LIMITED
+ Nu 98-2 Unoke
+ Kahoku-shi, Ishikawa 929-1192
+ JP
+
+70-B7-AA (hex) vivo Mobile Communication Co., Ltd.
+70B7AA (base 16) vivo Mobile Communication Co., Ltd.
+ #283,BBK Road
+ Wusha,Chang'An DongGuan City,Guangdong, 523860
+ CN
+
+1C-39-47 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+1C3947 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+34-66-EA (hex) VERTU INTERNATIONAL CORPORATION LIMITED
+3466EA (base 16) VERTU INTERNATIONAL CORPORATION LIMITED
+ 25 St Thomas Street, Winchester, Hampshire, United Kingdom
+ Winchester Hampshire SO23 9HJ
+ GB
+
+28-38-5C (hex) FLEXTRONICS
+28385C (base 16) FLEXTRONICS
+ Carretera Base Aerea 5850 int 4
+ Zapopan Jalisco 45136
+ MX
+
+74-1F-79 (hex) YOUNGKOOK ELECTRONICS CO.,LTD
+741F79 (base 16) YOUNGKOOK ELECTRONICS CO.,LTD
+ #810, Daewoo Frontier Valley 1,16-25, Dongbaekjungang-ro 16beon-gil, Giheung-gu
+ YONGIN Gyeonggi-do 17015
+ KR
+
+04-C3-E6 (hex) IEEE Registration Authority
+04C3E6 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+00-00-C3 (hex) Harris Corporation
+0000C3 (base 16) Harris Corporation
+ 1025 West NASA Blvd
+ Melbourne FL 32919
+ US
+
+B4-69-21 (hex) Intel Corporate
+B46921 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+DC-8B-28 (hex) Intel Corporate
+DC8B28 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+AC-92-32 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+AC9232 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+34-12-F9 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+3412F9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+4C-D1-A1 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+4CD1A1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+00-20-67 (hex) Private
+002067 (base 16) Private
+
+70-0B-01 (hex) Sagemcom Broadband SAS
+700B01 (base 16) Sagemcom Broadband SAS
+ 250, route de l'Empereur
+ Rueil Malmaison Cedex hauts de seine 92848
+ FR
+
+30-4B-07 (hex) Motorola Mobility LLC, a Lenovo Company
+304B07 (base 16) Motorola Mobility LLC, a Lenovo Company
+ 222 West Merchandise Mart Plaza
+ Chicago IL 60654
+ US
+
+40-17-E2 (hex) INTAI TECHNOLOGY CORP.
+4017E2 (base 16) INTAI TECHNOLOGY CORP.
+ No.9, JINGKE RD.,NANTUN DIST.
+ TAICHUNG CITY 40852
+ TW
+
+C0-48-FB (hex) Shenzhen JingHanDa Electronics Co.Ltd
+C048FB (base 16) Shenzhen JingHanDa Electronics Co.Ltd
+ 5th Floor,No 4 ,Road 1,ShangXue Technology industrial Park,LongGang district,ShenZhen,GuangDong,China
+ ShenZhen GuangDong 518129
+ CN
+
+24-7E-51 (hex) zte corporation
+247E51 (base 16) zte corporation
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
+ shenzhen guangdong 518057
+ CN
+
+6C-F9-D2 (hex) CHENGDU POVODO ELECTRONIC TECHNOLOGY CO., LTD
+6CF9D2 (base 16) CHENGDU POVODO ELECTRONIC TECHNOLOGY CO., LTD
+ High - West West West Center Road on the 4th
+ Chengdu Sichuan 611731
+ CN
+
+78-52-4A (hex) Ensenso GmbH
+78524A (base 16) Ensenso GmbH
+ Gundelfingerstr. 2
+ Freiburg 79108
+ DE
+
+94-C3-E4 (hex) Atlas Copco IAS GmbH
+94C3E4 (base 16) Atlas Copco IAS GmbH
+ Gewerbestr. 52
+ Bretten-Goelshausen 75015
+ DE
+
+00-02-3F (hex) Compal Electronics INC.
+00023F (base 16) Compal Electronics INC.
+ No.8 , Nandong Road , PingZhen Dist.
+ Taoyuan Taiwan 32455
+ TW
+
+E8-B5-41 (hex) zte corporation
+E8B541 (base 16) zte corporation
+ 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China
+ shenzhen guangdong 518057
+ CN
+
+E0-AF-4F (hex) Deutsche Telekom AG
+E0AF4F (base 16) Deutsche Telekom AG
+ Friedrich-Ebert-Allee 140
+ Bonn 53113
+ DE
+
+8C-41-F4 (hex) IPmotion GmbH
+8C41F4 (base 16) IPmotion GmbH
+ Ludwig-Rinn-Straße 8-16
+ Heuchelheim Hessen 35452
+ DE
+
+3C-89-94 (hex) BSkyB Ltd
+3C8994 (base 16) BSkyB Ltd
+ 130 Kings Road
+ Brentwood Essex 08854
+ GB
+
+F4-06-8D (hex) devolo AG
+F4068D (base 16) devolo AG
+ Charlottenburger Allee 67
+ Aachen NRW 52068
+ DE
+
+30-D3-2D (hex) devolo AG
+30D32D (base 16) devolo AG
+ Charlottenburger Allee 67
+ Aachen NRW 52068
+ DE
+
+A8-5A-F3 (hex) Shanghai Siflower Communication Technology Co., Ltd
+A85AF3 (base 16) Shanghai Siflower Communication Technology Co., Ltd
+ Rm. 408, No. 84, Lane 887. Zhangjiang Hi-Tech Park. Zuchongzhi Rd. Shanghai, China
+ Shanghai Shanghai 201210
+ CN
+
+4C-36-4E (hex) Panasonic Corporation Connected Solutions Company
+4C364E (base 16) Panasonic Corporation Connected Solutions Company
+ 4-1-62 Minoshima, Hakata-ku
+ Fukuoka-shi Fukuoka 812-8531
+ JP
+
+14-96-E5 (hex) Samsung Electronics Co.,Ltd
+1496E5 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+80-CE-B9 (hex) Samsung Electronics Co.,Ltd
+80CEB9 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+CC-21-19 (hex) Samsung Electronics Co.,Ltd
+CC2119 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+48-88-1E (hex) EthoSwitch LLC
+48881E (base 16) EthoSwitch LLC
+ 1298 Evans Road
+ Wall Township NJ 07719
+ US
+
+08-90-BA (hex) Danlaw Inc
+0890BA (base 16) Danlaw Inc
+ 23700 research Dr.
+ Farmington Hills 48335
+ US
+
+00-0F-15 (hex) Icotera A/S
+000F15 (base 16) Icotera A/S
+ Vibeholms Allé 16
+ Brøndby 2605
+ DK
+
+4C-11-59 (hex) Vision Information & Communications
+4C1159 (base 16) Vision Information & Communications
+ 151, Ulseong-gil
+ Pyeongtaek-si Gyeonggi-do 17823
+ KR
+
+B4-A9-4F (hex) MERCURY CORPORATION
+B4A94F (base 16) MERCURY CORPORATION
+ 90, Gajaeul-ro, Seo-gu
+ INCHEON 22830
+ KR
+
+E4-2D-7B (hex) China Mobile IOT Company Limited
+E42D7B (base 16) China Mobile IOT Company Limited
+ NO.8 Yu Ma Road, NanAn Area
+ Chongqing Chongqing 401336
+ CN
+
+C0-D0-FF (hex) China Mobile IOT Company Limited
+C0D0FF (base 16) China Mobile IOT Company Limited
+ NO.8 Yu Ma Road, NanAn Area
+ Chongqing Chongqing 401336
+ CN
+
+A0-95-0C (hex) China Mobile IOT Company Limited
+A0950C (base 16) China Mobile IOT Company Limited
+ NO.8 Yu Ma Road, NanAn Area
+ Chongqing Chongqing 401336
+ CN
+
+B0-53-65 (hex) China Mobile IOT Company Limited
+B05365 (base 16) China Mobile IOT Company Limited
+ NO.8 Yu Ma Road, NanAn Area
+ Chongqing Chongqing 401336
+ CN
+
+28-3E-76 (hex) Common Networks
+283E76 (base 16) Common Networks
+ 1390 Market St. Suite 820
+ San Francisco CA 94102
+ US
+
+48-F0-27 (hex) Chengdu newifi Co.,Ltd
+48F027 (base 16) Chengdu newifi Co.,Ltd
+ C11 Building 2001,No.219 ,2nd Tianhua Road,Hi-tech zone
+ Chengdu Sichuan 610000
+ CN
+
+58-D5-6E (hex) D-Link International
+58D56E (base 16) D-Link International
+ 1 Internal Business Park, #03-12,The Synergy, Singapore
+ Singapore Singapore 609917
+ SG
+
+1C-1B-B5 (hex) Intel Corporate
+1C1BB5 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+00-57-C1 (hex) LG Electronics (Mobile Communications)
+0057C1 (base 16) LG Electronics (Mobile Communications)
+ 60-39, Gasan-dong, Geumcheon-gu
+ Seoul 153-801
+ KR
+
+A8-9A-93 (hex) Sagemcom Broadband SAS
+A89A93 (base 16) Sagemcom Broadband SAS
+ 250, route de l'Empereur
+ Rueil Malmaison Cedex hauts de seine 92848
+ FR
+
+C8-54-4B (hex) Zyxel Communications Corporation
+C8544B (base 16) Zyxel Communications Corporation
+ No. 6 Innovation Road II, Science Park
+ Hsichu Taiwan 300
+ TW
+
+14-C6-97 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+14C697 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+ NO.18 HAIBIN ROAD,
+ DONG GUAN GUANG DONG 523860
+ CN
+
+DC-16-B2 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+DC16B2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+DC-90-88 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+DC9088 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+FC-03-9F (hex) Samsung Electronics Co.,Ltd
+FC039F (base 16) Samsung Electronics Co.,Ltd
+ 129, Samsung-ro, Youngtongl-Gu
+ Suwon Gyeonggi-Do 16677
+ KR
+
+E4-DB-6D (hex) Beijing Xiaomi Electronics Co., Ltd.
+E4DB6D (base 16) Beijing Xiaomi Electronics Co., Ltd.
+ Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District
+ Beijing Beijing 10085
+ CN
+
+B0-90-7E (hex) Cisco Systems, Inc
+B0907E (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+48-4A-E9 (hex) Hewlett Packard Enterprise
+484AE9 (base 16) Hewlett Packard Enterprise
+ 8000 Foothills Blvd.
+ Roseville CA 95747
+ US
+
+00-D0-D8 (hex) 3COM
+00D0D8 (base 16) 3COM
+ 2133 LEGHORN STREET
+ MOUNTAIN VIEW CA 94043
+ US
+
+00-01-02 (hex) 3COM
+000102 (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-04-76 (hex) 3COM
+000476 (base 16) 3COM
+ 5400 Bayfront Plaza
+ Santa Clara CA 95052
+ US
+
+00-26-6C (hex) INVENTEC CORPORATION
+00266C (base 16) INVENTEC CORPORATION
+ Inventec Building, 66 Hou-Kang Street Shih-Lin District,
+ Taipei 111
+ TW
+
+00-05-1A (hex) 3COM EUROPE LTD
+00051A (base 16) 3COM EUROPE LTD
+ 3COM CENTRE
+ UNITED KINGDOM
+ GB
+
+00-04-0B (hex) 3COM EUROPE LTD
+00040B (base 16) 3COM EUROPE LTD
+ BOUNDARY WAY
+ UNITED KINGDOM
+ GB
+
+00-10-5A (hex) 3COM
+00105A (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+00-18-49 (hex) nVent, Schroff GmbH
+001849 (base 16) nVent, Schroff GmbH
+ Langenalber Strasse 96-100
+ Straubenhardt 75334
+ DE
+
+9C-0C-DF (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+9C0CDF (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+ NO.18 HAIBIN ROAD,
+ DONG GUAN GUANG DONG 523860
+ CN
+
+58-B5-68 (hex) SECURITAS DIRECT ESPAÑA, SAU
+58B568 (base 16) SECURITAS DIRECT ESPAÑA, SAU
+ C/ Priégola, 2
+ Pozuelo de Alarcon Madrid 28224
+ ES
+
+14-22-33 (hex) Fiberhome Telecommunication Technologies Co.,LTD
+142233 (base 16) Fiberhome Telecommunication Technologies Co.,LTD
+ No.5 DongXin Road
+ Wuhan Hubei 430074
+ CN
+
+00-AA-6E (hex) Cisco Systems, Inc
+00AA6E (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+18-89-A0 (hex) Wuhan Funshion Online Technologies Co.,Ltd
+1889A0 (base 16) Wuhan Funshion Online Technologies Co.,Ltd
+ 5th Floor,Financial Port Building A9,No.77 Optical Valley Avenue, East Lake High-Tech Development Zone, Wuhan
+ Wuhan CN/Hubei 430000
+ CN
+
+88-F7-BF (hex) vivo Mobile Communication Co., Ltd.
+88F7BF (base 16) vivo Mobile Communication Co., Ltd.
+ #283,BBK Road
+ Wusha,Chang'An DongGuan City,Guangdong, 523860
+ CN
+
+00-01-21 (hex) WatchGuard Technologies, Inc.
+000121 (base 16) WatchGuard Technologies, Inc.
+ 605 Fifth Ave. S
+ Seattle WA 98104-3892
+ US
+
+54-6A-D8 (hex) Elster Water Metering Limited
+546AD8 (base 16) Elster Water Metering Limited
+ Mas des Cavaliers II, 471 Rue Charles Nungesser
+ Mauguio 34130
+ FR
+
+18-62-E4 (hex) Texas Instruments
+1862E4 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+68-47-49 (hex) Texas Instruments
+684749 (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+5C-D2-0B (hex) Yytek Co., Ltd.
+5CD20B (base 16) Yytek Co., Ltd.
+ No.1 Bao Sheng South Road, Room 401, Ao Bei Technology Park, Ling Zhi Center
+ Beijing 100192
+ CN
+
+74-83-C2 (hex) Ubiquiti Networks Inc.
+7483C2 (base 16) Ubiquiti Networks Inc.
+ 2580 Orchard Pkwy
+ San Jose CA 95131
+ US
+
+C0-84-7D (hex) AMPAK Technology, Inc.
+C0847D (base 16) AMPAK Technology, Inc.
+ No.1,Jen Ai Road Hsinchu Industrial Park, Hukou
+ Hsinchu Taiwan ROC. 30352
+ TW
+
+F8-D9-B8 (hex) Open Mesh, Inc.
+F8D9B8 (base 16) Open Mesh, Inc.
+ 111 SW 5th Ave Ste1150
+ Portland OR 97204
+ US
+
+E8-1C-BA (hex) Fortinet, Inc.
+E81CBA (base 16) Fortinet, Inc.
+ 899 Kifer Road
+ Sunnyvale 94086
+ US
+
+00-72-04 (hex) Samsung Electronics Co., Ltd. ARTIK
+007204 (base 16) Samsung Electronics Co., Ltd. ARTIK
+ 1-1, Samsungjeonja-ro
+ Hwaseong-si Gyeonggi-do 18448
+ KR
+
+28-6D-CD (hex) Beijing Winner Microelectronics Co.,Ltd.
+286DCD (base 16) Beijing Winner Microelectronics Co.,Ltd.
+ Floor 18, YinDu Building, No.67 FuCheng Road, HaiDian District
+ Beijing 100142
+ CN
+
+44-A4-66 (hex) GROUPE LDLC
+44A466 (base 16) GROUPE LDLC
+ Groupe LDLC - 2 rue des Erables
+ LIMONEST Rhone 69760
+ FR
+
2C-39-96 (hex) Sagemcom Broadband SAS
2C3996 (base 16) Sagemcom Broadband SAS
250 route de l'Empereur
@@ -117932,12 +119801,6 @@ B8FC9A (base 16) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited
Valence France 26902
FR
-34-BA-75 (hex) Tembo Systems, Inc.
-34BA75 (base 16) Tembo Systems, Inc.
- 2933 Bunker Hill Ln., Suite 100
- Santa Clara CA 95054
- US
-
94-86-CD (hex) SEOUL ELECTRONICS&TELECOM
9486CD (base 16) SEOUL ELECTRONICS&TELECOM
709, Namkwangcentrex 440-4, Cheongcheon-dong,
@@ -119867,12 +121730,6 @@ D855A3 (base 16) zte corporation
shenzhen guangdong 518057
CN
-80-09-02 (hex) Keysight Technologies, Inc.
-800902 (base 16) Keysight Technologies, Inc.
- 1400 Fountaingrove Pkwy.
- Santa Rosa CA 95403
- US
-
68-72-DC (hex) CETORY.TV Company Limited
6872DC (base 16) CETORY.TV Company Limited
Building C-1601, Tiley Central Plaza
@@ -120407,12 +122264,6 @@ D42F23 (base 16) Akenori PTE Ltd
Singapore 427447
SG
-28-63-36 (hex) Siemens AG - Industrial Automation - EWA
-286336 (base 16) Siemens AG - Industrial Automation - EWA
- Werner-von-Siemens Strasse 50
- Amberg 92224
- DE
-
38-F0-98 (hex) Vapor Stone Rail Systems
38F098 (base 16) Vapor Stone Rail Systems
10000 Cavendish
@@ -120497,12 +122348,6 @@ D8492F (base 16) CANON INC.
Ohta-ku Tokyo 146-8501
JP
-D4-67-61 (hex) SAHAB TECHNOLOGY
-D46761 (base 16) SAHAB TECHNOLOGY
- Office 20 - Qibla Tower
- Qibla
- KW
-
14-56-45 (hex) Savitech Corp.
145645 (base 16) Savitech Corp.
3F, No.309, Guangming 1st Rd.,
@@ -125630,12 +127475,6 @@ A05DE7 (base 16) DIRECTV, Inc.
San Jose CA 94568
US
-70-5A-B6 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-705AB6 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
00-3A-9A (hex) Cisco Systems, Inc
003A9A (base 16) Cisco Systems, Inc
80 West Tasman Drive
@@ -126146,12 +127985,6 @@ DC3350 (base 16) TechSAT GmbH
Tuningen Baden-Württemberg 78609
DE
-00-24-AE (hex) Morpho
-0024AE (base 16) Morpho
- 18 chaussee Jules Cesar
- OSNY 95520
- FR
-
00-24-A7 (hex) Advanced Video Communications Inc.
0024A7 (base 16) Advanced Video Communications Inc.
633 W 5th Street
@@ -131036,12 +132869,6 @@ DC3350 (base 16) TechSAT GmbH
SEOUL 153-023
KR
-00-12-4F (hex) Pentair Thermal Management
-00124F (base 16) Pentair Thermal Management
- 11004 - 174 St.
- Edmonton Alberta T5S 2P3
- CA
-
00-12-4A (hex) Dedicated Devices, Inc.
00124A (base 16) Dedicated Devices, Inc.
5680 E. Franklin Road
@@ -133112,12 +134939,6 @@ DC3350 (base 16) TechSAT GmbH
Yokohama Kanagawa 222-0033
JP
-02-C0-8C (hex) 3COM CORPORATION
-02C08C (base 16) 3COM CORPORATION
- 5400 BAYFRONT PLAZA
- SANTA CLARA CA 95052
- US
-
00-08-7B (hex) RTX Telecom A/S
00087B (base 16) RTX Telecom A/S
Stroemmen 6
@@ -133664,12 +135485,6 @@ DC3350 (base 16) TechSAT GmbH
302-0192
JP
-00-06-44 (hex) neix,Inc
-000644 (base 16) neix,Inc
- KKS Higashi-Sapporo Bldg.
- Shiroishi-ku, Sapporo-city Hokkaido 003-0003
- JP
-
00-06-4B (hex) Alexon Co., Ltd.
00064B (base 16) Alexon Co., Ltd.
3-207-1 Teramoto,
@@ -134024,12 +135839,6 @@ DC3350 (base 16) TechSAT GmbH
San Jose CA 95120
US
-00-06-EC (hex) Harris Corporation
-0006EC (base 16) Harris Corporation
- 1025 West NASA Blvd
- Melbourne FL 32919
- US
-
00-06-DF (hex) AIDONIC Corporation
0006DF (base 16) AIDONIC Corporation
2-7-10 Otsuka, Bunkyo-ku,
@@ -139466,12 +141275,6 @@ AA0000 (base 16) DIGITAL EQUIPMENT CORPORATION
Rueil Malmaison Cedex Hauts de Seine 92848
FR
-88-AE-1D (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
-88AE1D (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
- NO. 25, THE 3RD STREET KUNSHAN EXPORT PROCESSING ZONE
- KUNSHAN SUZHOU 215300
- CN
-
5C-35-3B (hex) Compal Broadband Networks, Inc.
5C353B (base 16) Compal Broadband Networks, Inc.
13F., No.1, Taiyuan 1st St.
@@ -142640,24 +144443,6 @@ C4F1D1 (base 16) BEIJING SOGOU TECHNOLOGY DEVELOPMENT CO., LTD.
Tokyo 100-8310
JP
-B0-C2-87 (hex) Technicolor CH USA Inc.
-B0C287 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-CC-03-FA (hex) Technicolor CH USA Inc.
-CC03FA (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-28-BE-9B (hex) Technicolor CH USA Inc.
-28BE9B (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
50-9F-3B (hex) OI ELECTRIC CO.,LTD
509F3B (base 16) OI ELECTRIC CO.,LTD
7-3-16 KIKUNA
@@ -142706,12 +144491,6 @@ FC3D93 (base 16) LONGCHEER TELECOMMUNICATION LIMITED
Shanghai Xuhui District 200233
CN
-48-F7-C0 (hex) Technicolor CH USA Inc.
-48F7C0 (base 16) Technicolor CH USA Inc.
- 5030 Sugarloaf Parkway
- Lawrenceville GA 30044
- US
-
00-40-9F (hex) Telco Systems, Inc.
00409F (base 16) Telco Systems, Inc.
15 Berkshire Road
@@ -143174,12 +144953,6 @@ C0854C (base 16) Ragentek Technology Group
Shenkeng Dist New Taipei City ---
TW
-0C-02-27 (hex) Technicolor CH USA Inc.
-0C0227 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
C0-28-8D (hex) Logitech, Inc
C0288D (base 16) Logitech, Inc
4700 NW Camas Meadows Drive
@@ -143729,12 +145502,6 @@ D8C8E9 (base 16) Phicomm (Shanghai) Co., Ltd.
Shanghai Shanghai 201616
CN
-64-F8-8A (hex) China Mobile IOT Company Limited
-64F88A (base 16) China Mobile IOT Company Limited
- NO.8 Yu Ma Road, NanAn Area Chongqing,China
- Chongqing Chongqing 401336
- CN
-
6C-49-C1 (hex) o2ones Co., Ltd.
6C49C1 (base 16) o2ones Co., Ltd.
503 Glory Tower, 3-10, Gumi-ro 9beon-gil, Bundang-gu
@@ -144086,18 +145853,6 @@ F00FEC (base 16) HUAWEI TECHNOLOGIES CO.,LTD
Seocho-gu Seoul 06778
KR
-54-A6-5C (hex) Technicolor CH USA Inc.
-54A65C (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
-C0-98-DA (hex) China Mobile IOT Company Limited
-C098DA (base 16) China Mobile IOT Company Limited
- NO.8 Yu Ma Road, NanAn Area Chongqing,China
- Chongqing Chongqing 401336
- CN
-
94-9F-3E (hex) Sonos, Inc.
949F3E (base 16) Sonos, Inc.
614 Chapala St
@@ -146942,12 +148697,6 @@ BC903A (base 16) Robert Bosch GmbH
Leonberg 71226
DE
-60-3D-26 (hex) Technicolor CH USA Inc.
-603D26 (base 16) Technicolor CH USA Inc.
- 101 West 103rd St.
- Indianapolis IN 46290
- US
-
38-20-A8 (hex) ColorTokens, Inc.
3820A8 (base 16) ColorTokens, Inc.
2101 Tasman Dr. Suite 200A
@@ -147242,80 +148991,638 @@ CC50E3 (base 16) Espressif Inc.
Shanghai Shanghai 201203
CN
-5C-B5-24 (hex) Sony Mobile Communications AB
-5CB524 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+DC-AF-68 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
+DCAF68 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
+ Gaoxin 2 Road, Free Trade Zone,Weifang,Shandong,261205,P.R.China
+ Weifang Shandong 261205
+ CN
+
+A0-19-B2 (hex) IEEE Registration Authority
+A019B2 (base 16) IEEE Registration Authority
+ 445 Hoes Lane
+ Piscataway NJ 08554
+ US
+
+88-B6-6B (hex) easynetworks
+88B66B (base 16) easynetworks
+ Rd kaituo 1# kaituohuiyuan B 1020, shangdi
+ Beijing 100084
+ CN
+
+D4-69-A5 (hex) Miura Systems Ltd.
+D469A5 (base 16) Miura Systems Ltd.
+ Axis 40, Oxford Road, Stokenchurch
+ High Wycombe Buckinghamshire HP143SX
+ GB
+
+60-3D-26 (hex) Technicolor CH USA Inc.
+603D26 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+54-A6-5C (hex) Technicolor CH USA Inc.
+54A65C (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+00-BC-60 (hex) Cisco Systems, Inc
+00BC60 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+28-BE-9B (hex) Technicolor CH USA Inc.
+28BE9B (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+CC-03-FA (hex) Technicolor CH USA Inc.
+CC03FA (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+B0-C2-87 (hex) Technicolor CH USA Inc.
+B0C287 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+48-F7-C0 (hex) Technicolor CH USA Inc.
+48F7C0 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+0C-02-27 (hex) Technicolor CH USA Inc.
+0C0227 (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+58-A4-8E (hex) PixArt Imaging Inc.
+58A48E (base 16) PixArt Imaging Inc.
+ No.5, Innovation Road 1, HsinChu Science Park,
+ Hsin-Chu 300
+ TW
+
+C0-B6-F9 (hex) Intel Corporate
+C0B6F9 (base 16) Intel Corporate
+ Lot 8, Jalan Hi-Tech 2/3
+ Kulim Kedah 09000
+ MY
+
+24-3A-82 (hex) IRTS
+243A82 (base 16) IRTS
+ 639 BD DES ARMARIS, IRTS
+ TOULON Provence Alpes Cotes d'Azur 83100
+ FR
+
+48-75-83 (hex) Intellion AG
+487583 (base 16) Intellion AG
+ Schuppisstrasse 10
+ St. Gallen St. Gallen 9016
+ CH
+
+9C-5C-F9 (hex) Sony Mobile Communications Inc
+9C5CF9 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-84-00-D2 (hex) Sony Mobile Communications AB
-8400D2 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+D4-38-9C (hex) Sony Mobile Communications Inc
+D4389C (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-90-C1-15 (hex) Sony Mobile Communications AB
-90C115 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+80-5E-4F (hex) FN-LINK TECHNOLOGY LIMITED
+805E4F (base 16) FN-LINK TECHNOLOGY LIMITED
+ A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District
+ SHENZHEN GUANGDONG 518100
+ CN
+
+9C-5A-44 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+9C5A44 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+5C-B5-24 (hex) Sony Mobile Communications Inc
+5CB524 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-8C-64-22 (hex) Sony Mobile Communications AB
-8C6422 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+84-00-D2 (hex) Sony Mobile Communications Inc
+8400D2 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-B4-52-7E (hex) Sony Mobile Communications AB
-B4527E (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+90-C1-15 (hex) Sony Mobile Communications Inc
+90C115 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-44-D4-E0 (hex) Sony Mobile Communications AB
-44D4E0 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+8C-64-22 (hex) Sony Mobile Communications Inc
+8C6422 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-84-8E-DF (hex) Sony Mobile Communications AB
-848EDF (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+B4-52-7E (hex) Sony Mobile Communications Inc
+B4527E (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-DC-AF-68 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD
-DCAF68 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD
- Gaoxin 2 Road, Free Trade Zone,Weifang,Shandong,261205,P.R.China
- Weifang Shandong 261205
- CN
-
-00-23-45 (hex) Sony Mobile Communications AB
-002345 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+44-D4-E0 (hex) Sony Mobile Communications Inc
+44D4E0 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-00-1C-A4 (hex) Sony Mobile Communications AB
-001CA4 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+84-8E-DF (hex) Sony Mobile Communications Inc
+848EDF (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-9C-5C-F9 (hex) Sony Mobile Communications AB
-9C5CF9 (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-23-45 (hex) Sony Mobile Communications Inc
+002345 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-D4-38-9C (hex) Sony Mobile Communications AB
-D4389C (base 16) Sony Mobile Communications AB
- 4-12-3 Higashi – Shinagaw
+00-1C-A4 (hex) Sony Mobile Communications Inc
+001CA4 (base 16) Sony Mobile Communications Inc
+ 4-12-3 Higashi – Shinagawa
Shinagawa-ku Tokyo 140-0002
JP
-A0-19-B2 (hex) IEEE Registration Authority
-A019B2 (base 16) IEEE Registration Authority
- 445 Hoes Lane
- Piscataway NJ 08554
+E4-1F-E9 (hex) Dunkermotoren GmbH
+E41FE9 (base 16) Dunkermotoren GmbH
+ Allmendstr. 11
+ Bonndorf Baden-Württemberg 79848
+ DE
+
+8C-6D-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+8C6D77 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+AC-75-1D (hex) HUAWEI TECHNOLOGIES CO.,LTD
+AC751D (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+64-13-31 (hex) Bosch Car Multimedia (Wuhu) Co. Ltd.
+641331 (base 16) Bosch Car Multimedia (Wuhu) Co. Ltd.
+ NO.48 North Yinhu Road
+ Wuhu city Anhui Province 241000
+ CN
+
+18-3A-48 (hex) VostroNet
+183A48 (base 16) VostroNet
+ GPO Box 3154
+ Brisbane Queensland 4000
+ AU
+
+78-0C-F0 (hex) Cisco Systems, Inc
+780CF0 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
US
+
+E0-12-83 (hex) Shenzhen Fanzhuo Communication Technology Co., Lt
+E01283 (base 16) Shenzhen Fanzhuo Communication Technology Co., Lt
+ No.1003 Kesi Road, Hi-Tech Park,
+ Shenzhen Nanshan District 2602-2603
+ CN
+
+84-A2-4D (hex) Birds Eye Systems Private Limited
+84A24D (base 16) Birds Eye Systems Private Limited
+ 123-126, B Wing First Floor, Chintanmani Plaza, Mohan Studio Compound, Andheri-Kurla Road, Andheri East
+ Mumbai Maharashtra 400099
+ IN
+
+A4-61-91 (hex) NamJunSa
+A46191 (base 16) NamJunSa
+ 12, Gimhae-daero 2635 beon-gil
+ Gimhae-si Gyeongsangnam-do 50932
+ KR
+
+88-D2-BF (hex) German Autolabs
+88D2BF (base 16) German Autolabs
+ Köpenicker Str. 154
+ Berlin Berlin 10997
+ DE
+
+24-D7-6B (hex) Syntronic AB
+24D76B (base 16) Syntronic AB
+ Utmarksvägen 33c
+ Gävle 80291
+ SE
+
+30-5D-A6 (hex) ADVALY SYSTEM Inc.
+305DA6 (base 16) ADVALY SYSTEM Inc.
+ 7 KITA2 NISHI2 CYUO-KU
+ SAPPORO HOKKAIDO 060-0002
+ JP
+
+40-A1-08 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.
+40A108 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd.
+ No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan
+ Wuhan Hubei 430000
+ CN
+
+C0-03-80 (hex) Juniper Networks
+C00380 (base 16) Juniper Networks
+ 1133 Innovation Way
+ Sunnyvale CA 94089
+ US
+
+D4-67-61 (hex) United Gulf Gate Co.
+D46761 (base 16) United Gulf Gate Co.
+ XonTel, Borj ALadel Tower, Fahad Al-Salem St Fl 21
+ Kuwait 0000
+ KW
+
+98-03-9B (hex) Mellanox Technologies, Inc.
+98039B (base 16) Mellanox Technologies, Inc.
+ 350 Oakmead Parkway, Suite 100
+ Sunnyvale CA 94085
+ US
+
+F8-27-2E (hex) Mercku
+F8272E (base 16) Mercku
+ 509 Beaver Creek Rd.
+ Waterloo Ontario N2V 2L3
+ CA
+
+44-4B-5D (hex) GE Healthcare
+444B5D (base 16) GE Healthcare
+ Kuortaneenkatu 2
+ Helsinki 00510
+ FI
+
+A0-93-51 (hex) Cisco Systems, Inc
+A09351 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+00-45-1D (hex) Cisco Systems, Inc
+00451D (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+70-5A-B6 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+705AB6 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+88-AE-1D (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+88AE1D (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD.
+ NO. 25, THE 3RD STREET KUNSHAN EXPORT PROCESSING ZONE
+ KUNSHAN SUZHOU 215300
+ CN
+
+98-BB-99 (hex) Phicomm (Sichuan) Co.,Ltd.
+98BB99 (base 16) Phicomm (Sichuan) Co.,Ltd.
+ 125 longquan street park road,longquan district,chengdu city
+ Sichuan Chengdu 610015
+ CN
+
+88-3F-99 (hex) Siemens AG
+883F99 (base 16) Siemens AG
+ Werner-von-Siemens-Str. 48
+ Amberg 92224
+ DE
+
+F4-F1-97 (hex) EMTAKE Inc
+F4F197 (base 16) EMTAKE Inc
+ 14, Pangyoyeok ro 192, Bundang gu
+ Seongnam city Kyeonggi do 13524
+ KR
+
+6C-ED-51 (hex) NEXCONTROL Co.,Ltd
+6CED51 (base 16) NEXCONTROL Co.,Ltd
+ (#303-1007, Ssangyong 3th) 397, Seokcheon-ro
+ Bucheon-si Gyeonggi-do 14449
+ KR
+
+F8-36-9B (hex) Texas Instruments
+F8369B (base 16) Texas Instruments
+ 12500 TI Blvd
+ Dallas TX 75243
+ US
+
+00-06-EC (hex) Harris Corporation
+0006EC (base 16) Harris Corporation
+ 1025 West NASA Blvd
+ Melbourne FL 32919
+ US
+
+28-63-36 (hex) Siemens AG
+286336 (base 16) Siemens AG
+ Werner-von-Siemens Strasse 50
+ Amberg 92224
+ DE
+
+34-79-16 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+347916 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+88-BF-E4 (hex) HUAWEI TECHNOLOGIES CO.,LTD
+88BFE4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+00-06-44 (hex) NextGen Business Solutions, Inc
+000644 (base 16) NextGen Business Solutions, Inc
+ KKS Higashi-Sapporo Bldg.3-5-3-24, Higashi-Sapporo
+ Shiroishi-ku, Sapporo-city Hokkaido 003-0003
+ JP
+
+00-24-AE (hex) IDEMIA
+0024AE (base 16) IDEMIA
+ 18 chaussee Jules Cesar
+ OSNY 95520
+ FR
+
+34-5A-BA (hex) tcloud intelligence
+345ABA (base 16) tcloud intelligence
+ Bao'an District, No. 400 Xiangshan Avenue
+ ShenZhen GuangDong 518105
+ CN
+
+50-2F-A8 (hex) Cisco Systems, Inc
+502FA8 (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+68-A8-E1 (hex) Wacom Co.,Ltd.
+68A8E1 (base 16) Wacom Co.,Ltd.
+ Sumitomo Fudosan Shinjuku Grand Tower 31F,8-17-1
+ Nishi-shinjuku,Shinjuku-ku Tokyo 160-6131
+ JP
+
+E8-A7-88 (hex) XIAMEN LEELEN TECHNOLOGY CO., LTD
+E8A788 (base 16) XIAMEN LEELEN TECHNOLOGY CO., LTD
+ 65 Sunban South Rd., Jimei North Industrial Zone,
+ Xiamen Fujian 361021
+ CN
+
+24-05-88 (hex) Google, Inc.
+240588 (base 16) Google, Inc.
+ 1600 Amphitheatre Parkway
+ Mountain View CA 94043
+ US
+
+58-2D-34 (hex) Qingping Electronics (Suzhou) Co., Ltd
+582D34 (base 16) Qingping Electronics (Suzhou) Co., Ltd
+ Room 304, A3 Building, NO.88 Dongchang Road, Suzhou Industrial Park
+ Suzhou Jiangsu Province 215028
+ CN
+
+B8-BE-F4 (hex) devolo AG
+B8BEF4 (base 16) devolo AG
+ Charlottenburger Allee 67
+ Aachen NRW 52068
+ DE
+
+30-23-03 (hex) Belkin International Inc.
+302303 (base 16) Belkin International Inc.
+ 12045 East Waterfront Drive
+ Playa Vista 90094
+ US
+
+98-AE-71 (hex) VVDN Technologies Pvt Ltd
+98AE71 (base 16) VVDN Technologies Pvt Ltd
+ B-22, Sec-34 , Info-city -I
+ Gurugram Haryana 122001
+ IN
+
+34-BA-75 (hex) Everest Networks, Inc
+34BA75 (base 16) Everest Networks, Inc
+ 2933 Bunker Hill Ln., Suite 100
+ Santa Clara CA 95054
+ US
+
+00-B5-D0 (hex) Samsung Electronics Co.,Ltd
+00B5D0 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+8C-83-E1 (hex) Samsung Electronics Co.,Ltd
+8C83E1 (base 16) Samsung Electronics Co.,Ltd
+ #94-1, Imsoo-Dong
+ Gumi Gyeongbuk 730-350
+ KR
+
+E4-FC-82 (hex) Juniper Networks
+E4FC82 (base 16) Juniper Networks
+ 1133 Innovation Way
+ Sunnyvale CA 94089
+ US
+
+00-12-4F (hex) nVent
+00124F (base 16) nVent
+ 1665 Utica Avenue, Suite 700
+ St Louis Park MN 55416
+ US
+
+64-F8-8A (hex) China Mobile IOT Company Limited
+64F88A (base 16) China Mobile IOT Company Limited
+ NO.8 Yu Ma Road, NanAn Area
+ Chongqing Chongqing 401336
+ CN
+
+C0-98-DA (hex) China Mobile IOT Company Limited
+C098DA (base 16) China Mobile IOT Company Limited
+ NO.8 Yu Ma Road, NanAn Area
+ Chongqing Chongqing 401336
+ CN
+
+18-93-7F (hex) AMPAK Technology, Inc.
+18937F (base 16) AMPAK Technology, Inc.
+ No.1,Jen Ai Road Hsinchu Industrial Park, Hukou
+ Hsinchu Taiwan ROC. 30352
+ TW
+
+A8-01-6D (hex) Aiwa Corporation
+A8016D (base 16) Aiwa Corporation
+ 965 W Chicago Ave
+ Chicago IL 60642
+ US
+
+B4-2E-99 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD.
+B42E99 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD.
+ Pin-Jen City, Taoyuan, Taiwan, R.O.C.
+ Pin-Jen Taoyuan 324
+ TW
+
+A4-9B-4F (hex) HUAWEI TECHNOLOGIES CO.,LTD
+A49B4F (base 16) HUAWEI TECHNOLOGIES CO.,LTD
+ No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park
+ Dongguan 523808
+ CN
+
+40-56-62 (hex) GuoTengShengHua Electronics LTD.
+405662 (base 16) GuoTengShengHua Electronics LTD.
+ 1st floor,No. 15 of Tech North 2nd Road,Nanshan District,
+ Shenzhen Guangdong 518000
+ CN
+
+24-2E-90 (hex) PALIT MICROSYSTEMS, LTD
+242E90 (base 16) PALIT MICROSYSTEMS, LTD
+ 21F.,No.88,Sec.2,Zhongxiao E.Rd.,Golden Tower,
+ TAIPEI 100
+ TW
+
+24-21-24 (hex) Nokia
+242124 (base 16) Nokia
+ 600 March Road
+ Kanata Ontario K2K 2E6
+ CA
+
+64-62-8A (hex) evon GmbH
+64628A (base 16) evon GmbH
+ Frank-Stronach-Straße 8
+ Gleisdorf Styria 8200
+ AT
+
+80-09-02 (hex) Keysight Technologies, Inc.
+800902 (base 16) Keysight Technologies, Inc.
+ 1400 Fountaingrove Pkwy.
+ Santa Rosa CA 95403
+ US
+
+02-C0-8C (hex) 3COM
+02C08C (base 16) 3COM
+ 5400 BAYFRONT PLAZA
+ SANTA CLARA CA 95052
+ US
+
+58-C8-76 (hex) China Mobile (Hangzhou) Information Technology Co., Ltd.
+58C876 (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd.
+ No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District
+ Hangzhou Zhejiang 310000
+ CN
+
+8C-8F-8B (hex) China Mobile Chongqing branch
+8C8F8B (base 16) China Mobile Chongqing branch
+ 6 building, No. 2, Xingguang three road
+ Yubei District Chongqing 401120
+ CN
+
+68-43-D7 (hex) Agilecom Photonics Solutions Guangdong Limited
+6843D7 (base 16) Agilecom Photonics Solutions Guangdong Limited
+ No.1-6, Shenwan Industrial Park, Shenwan Town
+ Zhongshan Guangdong 528462
+ CN
+
+88-34-FE (hex) Bosch Automotive Products (Suzhou) Co. Ltd
+8834FE (base 16) Bosch Automotive Products (Suzhou) Co. Ltd
+ No. 455 Xing Long Street,Suzhou Industrial Park,Suzhou P.R., 215021 China
+ Suzhou Jiangsu 215021
+ CN
+
+54-C3-3E (hex) Ciena Corporation
+54C33E (base 16) Ciena Corporation
+ 7035 Ridge Road
+ Hanover MD 21076
+ US
+
+00-A5-BF (hex) Cisco Systems, Inc
+00A5BF (base 16) Cisco Systems, Inc
+ 80 West Tasman Drive
+ San Jose CA 94568
+ US
+
+04-BC-87 (hex) Shenzhen JustLink Technology Co., LTD
+04BC87 (base 16) Shenzhen JustLink Technology Co., LTD
+ Room 5002,The 2nd Unit of the Building East, Laobing Building, No.3012 Xingye Road,Baoan District
+ Shenzhen Guangdong Province 518101
+ CN
+
+18-C2-BF (hex) BUFFALO.INC
+18C2BF (base 16) BUFFALO.INC
+ AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku
+ Nagoya Aichi Pref. 460-8315
+ JP
+
+D4-AB-82 (hex) ARRIS Group, Inc.
+D4AB82 (base 16) ARRIS Group, Inc.
+ 6450 Sequence Drive
+ San Diego CA 92121
+ US
+
+C4-4F-33 (hex) Espressif Inc.
+C44F33 (base 16) Espressif Inc.
+ Room 204, Building 2, 690 Bibo Road, Pudong New Area
+ Shanghai Shanghai 201203
+ CN
+
+70-03-7E (hex) Technicolor CH USA Inc.
+70037E (base 16) Technicolor CH USA Inc.
+ 5030 Sugarloaf Parkway Bldg 6
+ Lawrenceville GA 30044
+ US
+
+14-59-C0 (hex) NETGEAR
+1459C0 (base 16) NETGEAR
+ 350 East Plumeria Drive
+ San Jose CA 95134
+ US
+
+80-96-21 (hex) Lenovo
+809621 (base 16) Lenovo
+ 1009 Think Place
+ Morrisvilee NC 27560
+ US
+
+5C-C9-99 (hex) New H3C Technologies Co., Ltd
+5CC999 (base 16) New H3C Technologies Co., Ltd
+ 466 Changhe Road, Binjiang District
+ Hangzhou Zhejiang 310052
+ CN
+
+74-05-A5 (hex) TP-LINK TECHNOLOGIES CO.,LTD.
+7405A5 (base 16) TP-LINK TECHNOLOGIES CO.,LTD.
+ Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan
+ Shenzhen Guangdong 518057
+ CN
+
+B0-2A-43 (hex) Google, Inc.
+B02A43 (base 16) Google, Inc.
+ 1600 Amphitheatre Parkway
+ Mountain View CA 94043
+ US
+
+BC-AF-91 (hex) TE Connectivity Sensor Solutions
+BCAF91 (base 16) TE Connectivity Sensor Solutions
+ 4 rue Gaye-Marie, CS 83163
+ Toulouse 31027
+ FR
+
+EC-C4-0D (hex) Nintendo Co.,Ltd
+ECC40D (base 16) Nintendo Co.,Ltd
+ 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU
+ KYOTO KYOTO 601-8501
+ JP
diff --git a/hwdb/ma-medium.txt b/hwdb/ma-medium.txt
index 12165cb146..858409fe13 100644
--- a/hwdb/ma-medium.txt
+++ b/hwdb/ma-medium.txt
@@ -1643,9 +1643,6 @@ B00000-BFFFFF (base 16) Briowireless Inc.
Hangzhou Zhejiang 311200
CN
-F4-0E-11 (hex) Private
-F00000-FFFFFF (base 16) Private
-
78-D8-00 (hex) Shenzhen Envicool Information Technology Co., Ltd
100000-1FFFFF (base 16) Shenzhen Envicool Information Technology Co., Ltd
Building 9, Hongxin Industrial Park, Guanlan, Longhua District,
@@ -2198,9 +2195,6 @@ F00000-FFFFFF (base 16) Private
1C-CA-E3 (hex) Private
F00000-FFFFFF (base 16) Private
-D0-D9-4F (hex) Private
-700000-7FFFFF (base 16) Private
-
8C-1C-DA (hex) Anntec (Beijing) Technology Co.,Ltd.
400000-4FFFFF (base 16) Anntec (Beijing) Technology Co.,Ltd.
F803, Shangdi Third Street, No.9,HaiDian District
@@ -2237,17 +2231,158 @@ D00000-DFFFFF (base 16) Phasor Solutions Ltd
London EC1N 7RJ
GB
+2C-48-35 (hex) SureFlap Ltd
+900000-9FFFFF (base 16) SureFlap Ltd
+ 7 The Irwin Centre, Scotland Road, Dry Drayton
+ Cambridge Cambridgeshire CB23 8AR
+ GB
+
98-AA-FC (hex) Comarch S.A.
E00000-EFFFFF (base 16) Comarch S.A.
Al. Jana Pawla II 39A
Krakow Poland 31-864
PL
-2C-48-35 (hex) SureFlap Ltd
-900000-9FFFFF (base 16) SureFlap Ltd
- 7 The Irwin Centre, Scotland Road, Dry Drayton
- Cambridge Cambridgeshire CB23 8AR
- GB
+A0-19-B2 (hex) ARIMA Communications Corp.
+700000-7FFFFF (base 16) ARIMA Communications Corp.
+ 6F.,No.866,Zhongzheng Rd.,Zhonghe Dist.,
+ New Taipei City Taiwan 23586
+ TW
+
+D0-D9-4F (hex) Private
+700000-7FFFFF (base 16) Private
+
+F4-0E-11 (hex) Private
+F00000-FFFFFF (base 16) Private
+
+B4-4B-D6 (hex) ShenZhen Comstar Technology Company
+500000-5FFFFF (base 16) ShenZhen Comstar Technology Company
+ Pengnian Science Park Building A 314
+ Shenzhen Guangdong 518040
+ CN
+
+B4-4B-D6 (hex) Shenzhen Hi-Net Technology Co., Ltd.
+400000-4FFFFF (base 16) Shenzhen Hi-Net Technology Co., Ltd.
+ 3F, 4Building, Anda Industrial Zone, Chongqing Road, Fuyong Town, Baoan District
+ ShenZhen GuangDong 518103
+ CN
+
+3C-42-7E (hex) UBTECH ROBOTICS CORP
+800000-8FFFFF (base 16) UBTECH ROBOTICS CORP
+ 22 Floor, Block C1, Nanshan I Park, No. 1001 Xueyuan Road, Nanshan District,
+ Shenzhen guangdong 518071
+ CN
+
+3C-42-7E (hex) Xiaoniu network technology (Shanghai) Co., Ltd.
+E00000-EFFFFF (base 16) Xiaoniu network technology (Shanghai) Co., Ltd.
+ Room 706, building 3, no.20 east road, jingan district.
+ Shang hai 200040
+ CN
+
+04-C3-E6 (hex) Extech Electronics Co., LTD.
+300000-3FFFFF (base 16) Extech Electronics Co., LTD.
+ 17F., No.237, Sec. 1, Datong Rd., Xizhi Dist.
+ New Taipei City 22161
+ TW
+
+C0-83-59 (hex) PCH Engineering A/S
+300000-3FFFFF (base 16) PCH Engineering A/S
+ Ved Klaedebo 4
+ Horsholm 2970
+ DK
+
+C0-83-59 (hex) Viper Design, LLC
+500000-5FFFFF (base 16) Viper Design, LLC
+ 125 Glancy St.
+ Goodlettsville TN 37072
+ US
+
+C0-83-59 (hex) Gemvax Technology ,. Co.Ltd
+100000-1FFFFF (base 16) Gemvax Technology ,. Co.Ltd
+ 30, Techno1-ro, Yuseong-gu, Daejeon
+ Daejeon 34016
+ KR
+
+C0-83-59 (hex) Shenzhen Pay Device Technology Co., Ltd.
+900000-9FFFFF (base 16) Shenzhen Pay Device Technology Co., Ltd.
+ Room 502,Peng’s Building,Fanshen Road,43# Baoan District
+ Shenzhen Guangdong 518101
+ CN
+
+C0-83-59 (hex) Cyber Sciences, Inc.
+E00000-EFFFFF (base 16) Cyber Sciences, Inc.
+ 229 Castlewood Dr, Suite E
+ Murfreesboro TN 37129
+ US
+
+C0-83-59 (hex) Private
+C00000-CFFFFF (base 16) Private
+
+9C-F6-DD (hex) Foshan Synwit Technology Co.,Ltd.
+D00000-DFFFFF (base 16) Foshan Synwit Technology Co.,Ltd.
+ Room 501, Building 10, Leaguar Science Park, Shishan town, Nanhai
+ FoShan Guangdong 528225
+ CN
+
+9C-F6-DD (hex) b8ta Inc.
+500000-5FFFFF (base 16) b8ta Inc.
+ 164 Townsend St
+ San Francisco CA 94107
+ US
+
+30-09-F9 (hex) Shenzhen Tencent Computer System Co., Ltd.
+A00000-AFFFFF (base 16) Shenzhen Tencent Computer System Co., Ltd.
+ 5-10 Building High-tech Zone, Nanshan District,
+ Shenzhen Guangdong Province 518057
+ CN
+
+30-09-F9 (hex) Maytronics Ltd.
+700000-7FFFFF (base 16) Maytronics Ltd.
+ Kibbutz Yizrael
+ Kibbutz Yizrael 1935000
+ IL
+
+84-89-EC (hex) EPSa Elektronik & Präzisionsbau Saalfeld GmbH
+B00000-BFFFFF (base 16) EPSa Elektronik & Präzisionsbau Saalfeld GmbH
+ Remschuetzer Str. 1
+ Saalfeld/Saale 07318
+ DE
+
+84-89-EC (hex) POCT biotechnology
+600000-6FFFFF (base 16) POCT biotechnology
+ 6F, No. 185, GangQian Rd., Neihu dist.,
+ Taipei 11494
+ TW
+
+A0-28-33 (hex) Audix
+D00000-DFFFFF (base 16) Audix
+ 9400 SW Barber St.
+ Wilsonville OR 97070
+ US
+
+A0-28-33 (hex) JGR Optics Inc
+500000-5FFFFF (base 16) JGR Optics Inc
+ 160 Michael Cowpland Drive
+ Ottawa Ontario K2M 1P6
+ CA
+
+A4-ED-43 (hex) NETAS TELEKOMUNIKASYON A.S.
+400000-4FFFFF (base 16) NETAS TELEKOMUNIKASYON A.S.
+ Kurtköy Mahallesi, Osmanlı Blv. No:11
+ Pendik Istanbul 34912
+ TR
+
+A4-ED-43 (hex) INGELABS S.L.
+100000-1FFFFF (base 16) INGELABS S.L.
+ Av. Juan Lopez Peñalver, 21
+ Malaga Malaga 29590
+ ES
+
+A4-ED-43 (hex) Brand New Brand Nordic AB
+D00000-DFFFFF (base 16) Brand New Brand Nordic AB
+ Nohrstedts väg 5
+ Söderbärke 77794
+ SE
1C-87-76 (hex) Strone Technology
C00000-CFFFFF (base 16) Strone Technology
@@ -3290,12 +3425,6 @@ CC-D3-1E (hex) SAMIM Co
Tehran Tehran 1581633939
IR
-CC-D3-1E (hex) Fluidic Energy
-C00000-CFFFFF (base 16) Fluidic Energy
- 8455 North 90th Street
- Scottsdale AZ 85258
- US
-
CC-D3-1E (hex) NTmore.Co.,Ltd
500000-5FFFFF (base 16) NTmore.Co.,Ltd
38, Heungan-daero 427 beon-gil, Dongan-gu
@@ -4028,9 +4157,6 @@ A00000-AFFFFF (base 16) Trilux Group Management GmbH
Suzhou JiangSu 215021
CN
-1C-A0-D3 (hex) Private
-700000-7FFFFF (base 16) Private
-
A4-11-63 (hex) AlterG, Inc.
400000-4FFFFF (base 16) AlterG, Inc.
48438 Milmont Drive
@@ -4187,9 +4313,6 @@ A0-C5-F2 (hex) Shenzhen Feima Robotics Technology Co.,Ltd
Shenzhen Guangdong 518000
CN
-B0-1F-81 (hex) Private
-F00000-FFFFFF (base 16) Private
-
7C-BA-CC (hex) Fortem Technologies, Inc.
500000-5FFFFF (base 16) Fortem Technologies, Inc.
1712 S East Bay Boulevard Suite 325
@@ -4232,9 +4355,6 @@ A00000-AFFFFF (base 16) Honeywell Safety Products USA, Inc
San Diego CA 92154
US
-B0-C5-CA (hex) Private
-F00000-FFFFFF (base 16) Private
-
34-00-8A (hex) Fotonic i Norden AB
400000-4FFFFF (base 16) Fotonic i Norden AB
Box 733
@@ -4442,6 +4562,225 @@ A00000-AFFFFF (base 16) Collatz+Trojan GmbH
7C-70-BC (hex) Private
F00000-FFFFFF (base 16) Private
+A0-19-B2 (hex) Lon Microsystems Inc.
+900000-9FFFFF (base 16) Lon Microsystems Inc.
+ 11F Ali center Tianfu four street
+ chengdu sichuan 610041
+ CN
+
+A0-19-B2 (hex) LDA Technologies
+C00000-CFFFFF (base 16) LDA Technologies
+ 2680 Matheson Blvd E., Suite 102
+ Mississauga Ontario L4W2C6
+ CA
+
+1C-A0-D3 (hex) Private
+700000-7FFFFF (base 16) Private
+
+D4-7C-44 (hex) Innoviz Technologies LTD
+100000-1FFFFF (base 16) Innoviz Technologies LTD
+ Atir Yeda 15
+ Kfar Saba Ha Sharon 4464312
+ IL
+
+D4-7C-44 (hex) YunDing Network Technology (Beijing) Co., Ltd
+200000-2FFFFF (base 16) YunDing Network Technology (Beijing) Co., Ltd
+ A521,Floor 5, Tencent Space Building No.388, Hui long guan East St.
+ Beijing 100000
+ CN
+
+D4-7C-44 (hex) ASDA ICT Co., Ltd.
+600000-6FFFFF (base 16) ASDA ICT Co., Ltd.
+ 4F-2,No.2,Sec.4,Zhongyang Rd,Tucheng Dist,
+ New Taipei City 999079
+ TW
+
+D4-7C-44 (hex) Exafore Oy
+000000-0FFFFF (base 16) Exafore Oy
+ Hermiankatu 6-8D
+ Tampere 33720
+ FI
+
+B4-4B-D6 (hex) G4S Monitoring Technologies Ltd
+000000-0FFFFF (base 16) G4S Monitoring Technologies Ltd
+ 3 Centurion Court, Meridian East
+ Leicester Leicestershire LE19 1TP
+ GB
+
+B4-4B-D6 (hex) SHENZHEN TITA INTERACTIVE TECHNOLOGY CO.,LTD
+100000-1FFFFF (base 16) SHENZHEN TITA INTERACTIVE TECHNOLOGY CO.,LTD
+ Floor 23, Haowei Technology Mansion,Keji south eighth Road, Gaoxin Sci-Tech. Park(South Zone),
+ Shenzhen Guangdong 518000
+ CN
+
+B4-4B-D6 (hex) Shenzhen Huabai Intelligent Technology Co., Ltd.
+A00000-AFFFFF (base 16) Shenzhen Huabai Intelligent Technology Co., Ltd.
+ Science Park South District Shenzhen Digital
+ Technology Park Building B2 4th Floor Area A Shenzhen, Guangdong 518000
+ CN
+
+3C-42-7E (hex) ROBOX SMART MOTION (WUHU) CO.,LTD
+D00000-DFFFFF (base 16) ROBOX SMART MOTION (WUHU) CO.,LTD
+ No.96,Wanchun East Road,Jiujiang Economic Development District,Wuhu,Anhui,China
+ Wuhu Anhui 241000
+ CN
+
+B4-4B-D6 (hex) Perspicace Intellegince Technology
+600000-6FFFFF (base 16) Perspicace Intellegince Technology
+ 4F, 1326#, West YanAn road, Shanghai, P.R.China
+ ShangHai ShangHai 200052
+ CN
+
+B0-1F-81 (hex) Private
+F00000-FFFFFF (base 16) Private
+
+3C-42-7E (hex) Dongguan Taide Industrial Co.,Ltd.
+100000-1FFFFF (base 16) Dongguan Taide Industrial Co.,Ltd.
+ Taide Industrial Park,Phase 2 Jinfenghuang Industrial District Huangdong,Fenggang Town
+ Dongguan City GuangDong 523696
+ CN
+
+CC-D3-1E (hex) NantEnergy
+C00000-CFFFFF (base 16) NantEnergy
+ 8455 North 90th Street Suite 4
+ Scottsdale AZ 85258
+ US
+
+A0-19-B2 (hex) Adomi
+A00000-AFFFFF (base 16) Adomi
+ 777 Mariners Island Blvd. Suite 150
+ San Mateo CA 94404
+ US
+
+04-C3-E6 (hex) DREAMKAS LLC
+000000-0FFFFF (base 16) DREAMKAS LLC
+ Bolshoy Sampsoniyevskiy pr., 62A, office 2H
+ Saint-Petersburg 194044
+ RU
+
+C0-83-59 (hex) Suzhou Siheng Science and Technology Ltd.
+B00000-BFFFFF (base 16) Suzhou Siheng Science and Technology Ltd.
+ 8 floor of Jincheng star, Yunhe road NO.150, gaoxin Zone, Suzhou
+ Suzhou 215000
+ CN
+
+04-C3-E6 (hex) Teleepoch Ltd
+E00000-EFFFFF (base 16) Teleepoch Ltd
+ No.13 Langshan Rd,HiTech Park,Nanshan District
+ Shenzhen Guangdong 518000
+ CN
+
+C0-83-59 (hex) SHANGHAI CHARMHOPE INFORMATION TECHNOLOGY CO.,LTD.
+A00000-AFFFFF (base 16) SHANGHAI CHARMHOPE INFORMATION TECHNOLOGY CO.,LTD.
+ Building 11,No.230,Chuanhong Rd,Pudong Distrist
+ Shanghai Shanghai 201202
+ CN
+
+B0-C5-CA (hex) Private
+F00000-FFFFFF (base 16) Private
+
+C0-83-59 (hex) ANTS
+400000-4FFFFF (base 16) ANTS
+ 88, Simindae-ro, Dongan-Gu
+ Anyang 14079
+ KR
+
+9C-F6-DD (hex) Lighting New Energy Technology Co., Ltd.
+C00000-CFFFFF (base 16) Lighting New Energy Technology Co., Ltd.
+ Room 402, Building 22, Chentian Industrial Zone, Xixiang Street, Bao'an District,
+ Shenzhen Guangdong 518100
+ CN
+
+9C-F6-DD (hex) Ithor IT Co.,Ltd.
+100000-1FFFFF (base 16) Ithor IT Co.,Ltd.
+ No. 501, Building I, ZTE Park, Hi-Tech Industrial Zone
+ XI'AN ShanXi 710065
+ CN
+
+9C-F6-DD (hex) Savari Inc
+800000-8FFFFF (base 16) Savari Inc
+ 2005 De la cruz blvd, st 111,
+ santa clara CA 95050
+ US
+
+30-09-F9 (hex) Honeywell
+C00000-CFFFFF (base 16) Honeywell
+ 13350 US Hwy 19 N
+ Clearwater 33764
+ US
+
+30-09-F9 (hex) Beijing Mydreamplus Information Technology Co., Ltd.
+600000-6FFFFF (base 16) Beijing Mydreamplus Information Technology Co., Ltd.
+ Room 301-2, North Building, No. 11, CangJingGuan Lane, DongCheng District,
+ Beijing Beijing 100005
+ CN
+
+30-09-F9 (hex) Beijing Netswift Technology Co.,Ltd.
+200000-2FFFFF (base 16) Beijing Netswift Technology Co.,Ltd.
+ No. 7, 7th floor, No.49 Zhichun Road, Haidian District
+ Beijing Beijing 100190
+ CN
+
+84-89-EC (hex) Price Industries Limited
+D00000-DFFFFF (base 16) Price Industries Limited
+ 638 Raleigh Street
+ Winnipeg Manitoba R2K3Z9
+ CA
+
+84-89-EC (hex) thousand star tech LTD.
+200000-2FFFFF (base 16) thousand star tech LTD.
+ guan nan yuan 1 road dangdai optical valley dream workshop
+ wuhan hubei 430070
+ CN
+
+84-89-EC (hex) Newell Brands
+A00000-AFFFFF (base 16) Newell Brands
+ 221 River Street
+ Hoboken NJ 07030
+ US
+
+84-89-EC (hex) SHINKAWA LTD.
+C00000-CFFFFF (base 16) SHINKAWA LTD.
+ Shinjuku Front Tower 32F, 2-21-1 Kitashinjyuku
+ Shinjuku-ku Tokyo 169-0074
+ JP
+
+84-89-EC (hex) Shenzhen Intellifusion Technologies Co., Ltd.
+E00000-EFFFFF (base 16) Shenzhen Intellifusion Technologies Co., Ltd.
+ Suite701, Science Museum, Shenzhen City
+ Shenzhen Guangdong 518000
+ CN
+
+A0-28-33 (hex) IMESHX CORPORATION LIMITED
+900000-9FFFFF (base 16) IMESHX CORPORATION LIMITED
+ 10A7F, ShenZhen Bay Technology Ecological Park, NanShan District,
+ Shenzhen Guangdong 518000
+ CN
+
+A0-28-33 (hex) Precision Planting, LLC.
+E00000-EFFFFF (base 16) Precision Planting, LLC.
+ 23207 Townline Rd.
+ Tremont IL 61568
+ US
+
+A4-ED-43 (hex) Heyuan intelligence technology CO.,Ltd
+900000-9FFFFF (base 16) Heyuan intelligence technology CO.,Ltd
+ No.1166 Xinluo Street
+ Jinan City Shandong Province 250101
+ CN
+
+A4-ED-43 (hex) Sweam AB
+000000-0FFFFF (base 16) Sweam AB
+ Kistagången 12
+ Kista Stockholm 16440
+ SE
+
+A4-ED-43 (hex) Linseis Messgeraete GmbH
+800000-8FFFFF (base 16) Linseis Messgeraete GmbH
+ Vielitzer Str. 43
+ Selb 95100
+ DE
+
1C-87-76 (hex) Zhuhai MYZR Technology Co.,Ltd
500000-5FFFFF (base 16) Zhuhai MYZR Technology Co.,Ltd
Room 302,Area D2,National Hi-tech Zone,NO.1,Software Park Road
@@ -5612,12 +5951,6 @@ C00000-CFFFFF (base 16) You Zhengcheng co.,ltd
Albany CA 94706
US
-1C-21-D1 (hex) Private
-F00000-FFFFFF (base 16) Private
-
-C8-8E-D1 (hex) Private
-F00000-FFFFFF (base 16) Private
-
28-36-38 (hex) CHARGELIB
500000-5FFFFF (base 16) CHARGELIB
11 CITE VANEAU
@@ -5930,9 +6263,6 @@ A4-58-0F (hex) Stone Lock Global, Inc.
skien 3724
NO
-34-04-9E (hex) Private
-900000-9FFFFF (base 16) Private
-
50-A4-D0 (hex) XinLian'AnBao(Beijing)Technology Co.,LTD.
800000-8FFFFF (base 16) XinLian'AnBao(Beijing)Technology Co.,LTD.
(Room 501,Building 10, Area 2, Headquarters Base)NO.188,South 4th Ring West Road, Fengtai District
@@ -6221,9 +6551,6 @@ A00000-AFFFFF (base 16) annapurnalabs
Hong Kong Hong Kong 9998800
HK
-88-5D-90 (hex) Private
-F00000-FFFFFF (base 16) Private
-
28-F5-37 (hex) Skyrockettoys LLC
D00000-DFFFFF (base 16) Skyrockettoys LLC
12910 culver blvd Ste F
@@ -6260,9 +6587,6 @@ A00000-AFFFFF (base 16) Virtual Trunk Pte Ltd
Aperia #04-30 339511
SG
-DC-44-27 (hex) Private
-F00000-FFFFFF (base 16) Private
-
18-9B-A5 (hex) Christ Electronic System GmbH
C00000-CFFFFF (base 16) Christ Electronic System GmbH
Alpenstrasse 34
@@ -6344,6 +6668,237 @@ B00000-BFFFFF (base 16) Tolomatic, Inc.
Hamel MN 55340
US
+28-2C-02 (hex) SHENZHEN DOMENOR TECHNOLOGY LLC
+D00000-DFFFFF (base 16) SHENZHEN DOMENOR TECHNOLOGY LLC
+ F4, BUILDING A3, SILICON VALLEY POWER TECHNOLOGY PARK, SILI ROAD, KUKENG COMMUNITY, GUANLAN TOWN,LONGHUA DISTRICT
+ SHENZHEN GUANGDONG 518110
+ CN
+
+9C-43-1E (hex) Symfun Telecom Ltd
+100000-1FFFFF (base 16) Symfun Telecom Ltd
+ Floor 4 Building 11 Xi Qi Dian Jia Yuan
+ Beijing 100083
+ CN
+
+9C-43-1E (hex) Antailiye Technology Co.,Ltd
+000000-0FFFFF (base 16) Antailiye Technology Co.,Ltd
+ 7/F,Zhengjiyuan Buiding,2 Road,Qianjing, Xixiang, Baoan District,Shenzhen
+ SHEN ZHEN GUANGDONG 518000
+ CN
+
+9C-43-1E (hex) ST Access Control System Corp.
+A00000-AFFFFF (base 16) ST Access Control System Corp.
+ 3F., No. 111 Zhongzheng Rd., Banciao Dist., New Taipei City
+ New Taipei City 22054
+ TW
+
+C4-FF-BC (hex) Mobiletron Electronics Co., Ltd
+200000-2FFFFF (base 16) Mobiletron Electronics Co., Ltd
+ 85, Sec.4, Chung-Ching Rd., Ta-Ya District
+ Taichung 428
+ TW
+
+C4-FF-BC (hex) iMageTech CO.,LTD.
+400000-4FFFFF (base 16) iMageTech CO.,LTD.
+ 5F., No.16, Lane 15, Sec. 6, Mincyuan E. Rd., Neihu District,
+ TAIPEI 114
+ TW
+
+C4-FF-BC (hex) KAGA ELECTRONICS CO.,LTD.
+B00000-BFFFFF (base 16) KAGA ELECTRONICS CO.,LTD.
+ 20 Kandamatsunaga-cho
+ Chiyoda-ku TOKYO 101-8627
+ JP
+
+C4-FF-BC (hex) comtime GmbH
+500000-5FFFFF (base 16) comtime GmbH
+ Gutenbergring 22
+ Norderstedt 22848
+ US
+
+DC-E5-33 (hex) Tintel Hongkong Co.Ltd
+B00000-BFFFFF (base 16) Tintel Hongkong Co.Ltd
+ FLAT C,23/F,LUCKY PLAZA,315-321 LOCKHART ROAD,WANCHAI,HONGKONG
+ HONGKONG GUANG DONG PROVINCE 999077
+ HK
+
+DC-E5-33 (hex) JB-Lighting Lichtanlagen GmbH
+800000-8FFFFF (base 16) JB-Lighting Lichtanlagen GmbH
+ Sallersteig 15
+ 89134 89134
+ DE
+
+DC-E5-33 (hex) Giant Power Technology Biomedical Corporation
+E00000-EFFFFF (base 16) Giant Power Technology Biomedical Corporation
+ Rm201, 2nd Educational Building, No. 84, Gongzhuan Rd, Taishan Dist
+ New Taipei City 24301
+ TW
+
+DC-E5-33 (hex) shenzhen bangying electronics co,.ltd
+400000-4FFFFF (base 16) shenzhen bangying electronics co,.ltd
+ 3/F Building 16,Hongfa industrialPark,Tangtou Shiyan Town
+ shenzhen guangdong 518000
+ CN
+
+A4-DA-22 (hex) AURANEXT
+600000-6FFFFF (base 16) AURANEXT
+ 202 quai de clichy
+ CLICHY 92110
+ FR
+
+A4-DA-22 (hex) Wyze Labs Inc
+200000-2FFFFF (base 16) Wyze Labs Inc
+ 22522 29TH DR SE L101
+ BOTHELL WA 98021
+ US
+
+A4-DA-22 (hex) LORIOT AG
+400000-4FFFFF (base 16) LORIOT AG
+ Zuercherstrasse 68
+ Thalwil Zürich 8800
+ CH
+
+A4-DA-22 (hex) DURATECH Enterprise,LLC
+300000-3FFFFF (base 16) DURATECH Enterprise,LLC
+ NO.1013,184,Gasan digital 2-ro,Geumcheon-gu,Seoul
+ Seoul 08501
+ KR
+
+A4-DA-22 (hex) EHO.LINK
+C00000-CFFFFF (base 16) EHO.LINK
+ 5 Avenue de Saint Menet, Imm. Axiome, Bat. B
+ Marseille 13011
+ FR
+
+A4-DA-22 (hex) General Electric Company
+000000-0FFFFF (base 16) General Electric Company
+ Valle del Cedro #1551
+ Ciudad Juarez Chih 32575
+ MX
+
+88-A9-A7 (hex) Mikroelektronika
+300000-3FFFFF (base 16) Mikroelektronika
+ Batajnicki drum 23
+ Belgrade 11186
+ RS
+
+88-A9-A7 (hex) kimura giken corporation
+700000-7FFFFF (base 16) kimura giken corporation
+ 4-9-19 kamiyoga
+ Setagaya-ku Tokyo 158-0098
+ JP
+
+88-A9-A7 (hex) FlashForge Corporation
+900000-9FFFFF (base 16) FlashForge Corporation
+ No.518, Xianyuan Road
+ Jinhua Zhejiang 321000
+ CN
+
+88-A9-A7 (hex) Thomas & Darden, Inc
+400000-4FFFFF (base 16) Thomas & Darden, Inc
+ 916 Springdale Rd Bldg 4 #104
+ Austin 78702
+ US
+
+88-A9-A7 (hex) Impact Distribution
+E00000-EFFFFF (base 16) Impact Distribution
+ Ter Heidelaan 50a
+ Aarschot 3200
+ BE
+
+88-A9-A7 (hex) Honeywell spol. s.r.o. HTS CZ o.z.
+200000-2FFFFF (base 16) Honeywell spol. s.r.o. HTS CZ o.z.
+ Turanka 100/1387
+ Brno 62700
+ CZ
+
+88-A9-A7 (hex) Solaredge LTD.
+100000-1FFFFF (base 16) Solaredge LTD.
+ Hamada 1
+ Herzelia 4673335
+ IL
+
+F0-41-C8 (hex) Candelic Limited
+400000-4FFFFF (base 16) Candelic Limited
+ Unit 312, 3/F Solo Workshop, 131-132 Cannaught Road West
+ Hong Kong 111111
+ HK
+
+F0-41-C8 (hex) POSTIUM KOREA CO., LTD.
+800000-8FFFFF (base 16) POSTIUM KOREA CO., LTD.
+ A208 Samsong Techno Valley, 140 Tongil-ro, Deogyang-gu
+ Koyang-si Kyeonggi-do 10594
+ KR
+
+88-5F-E8 (hex) Beijing laiwei Technology Co.,Ltd
+400000-4FFFFF (base 16) Beijing laiwei Technology Co.,Ltd
+ Room 205,2/F,No.1 Fazhan Road Beijing information international base Huilongguan town Changping district Beijing
+ Beijing Beijing 102206
+ CN
+
+88-5F-E8 (hex) Shenzhen Xin Kingbrand Enterprises Co.,Ltd
+600000-6FFFFF (base 16) Shenzhen Xin Kingbrand Enterprises Co.,Ltd
+ KingBrand Industrial Zone, Nanpu Road,Shang Liao Lin Pikeng,Shajing Town,Baoan District
+ Shenzhen 518000
+ CN
+
+48-0B-B2 (hex) annapurnalabs
+600000-6FFFFF (base 16) annapurnalabs
+ HACRMEL 2 st Brosh BLDG FLOOR3
+ YOKNEAM. POB 218 Israel 26814
+ IL
+
+48-0B-B2 (hex) BAJA ELECTRONICS TECHNOLOGY LIMITED
+100000-1FFFFF (base 16) BAJA ELECTRONICS TECHNOLOGY LIMITED
+ 403, Unit 3, Building 3, Zhongdian Hi-Tech Park, No.1 Kejiqi Rd.
+ Zhuhai Guangdong 519080
+ CN
+
+0C-73-EB (hex) Dinkle Enterprise Co., Ltd.
+700000-7FFFFF (base 16) Dinkle Enterprise Co., Ltd.
+ No.19, Wuquan 2nd Rd., Wugu Dist.
+ New Taipei City 24890
+ TW
+
+3C-24-F0 (hex) COMATIS
+B00000-BFFFFF (base 16) COMATIS
+ 8 rue Carnot
+ SAINT-CYR-L'ECOLE 78210
+ FR
+
+8C-1C-DA (hex) Septentrio NV
+500000-5FFFFF (base 16) Septentrio NV
+ Interleuvenlaan 15i
+ Leuven 3001
+ BE
+
+80-E4-DA (hex) Private
+F00000-FFFFFF (base 16) Private
+
+74-19-F8 (hex) Private
+F00000-FFFFFF (base 16) Private
+
+2C-48-35 (hex) Newtrax Technologies Inc
+300000-3FFFFF (base 16) Newtrax Technologies Inc
+ 360 St-Jacques, Floor 8
+ Montreal Quebec H2Y 1P5
+ CA
+
+BC-34-00 (hex) Private
+F00000-FFFFFF (base 16) Private
+
+74-F8-DB (hex) Ballard Technology, Inc,
+A00000-AFFFFF (base 16) Ballard Technology, Inc,
+ 11400 Airport Rd
+ Everett Wa 98204
+ US
+
+2C-48-35 (hex) IROOTECH TECHNOLOGY CO.,LTD
+E00000-EFFFFF (base 16) IROOTECH TECHNOLOGY CO.,LTD
+ Room 606, Floor 6, Building 5, Eastern Yard 10, Xibeiwang East Road
+ Beijing 100092
+ CN
+
AC-1D-DF (hex) Shenzheng SenseTime Technology Co. Ltd
600000-6FFFFF (base 16) Shenzheng SenseTime Technology Co. Ltd
7F,Haixiang plaza, No.1052 Nanhai Road, Nanshan district
@@ -6566,243 +7121,261 @@ C00000-CFFFFF (base 16) Santec Corporation
Komaki Aichi 485-0802
JP
-28-2C-02 (hex) SHENZHEN DOMENOR TECHNOLOGY LLC
-D00000-DFFFFF (base 16) SHENZHEN DOMENOR TECHNOLOGY LLC
- F4, BUILDING A3, SILICON VALLEY POWER TECHNOLOGY PARK, SILI ROAD, KUKENG COMMUNITY, GUANLAN TOWN,LONGHUA DISTRICT
- SHENZHEN GUANGDONG 518110
+A0-19-B2 (hex) MIS Industrie Systeme GmbH & Co. KG
+800000-8FFFFF (base 16) MIS Industrie Systeme GmbH & Co. KG
+ Lohwiese 7
+ Scheuring Bavaria 86937
+ DE
+
+A0-19-B2 (hex) Power Diagnostic Service Co., LTD.
+300000-3FFFFF (base 16) Power Diagnostic Service Co., LTD.
+ No.10, Ln.482, Sec.4 Zhonghua Rd.
+ Hsinchu City 30094
+ TW
+
+A0-19-B2 (hex) Ahgora Sistemas SA
+E00000-EFFFFF (base 16) Ahgora Sistemas SA
+ Rodovia José Carlos Daux (SC-401), 600 (Km 01) - ParqTec Alfa - Módulo 08
+ Florianópolis Santa Catarina 88030000
+ BR
+
+D4-7C-44 (hex) STRIVE ORTHOPEDICS INC
+C00000-CFFFFF (base 16) STRIVE ORTHOPEDICS INC
+ 505 PARK AVE FL 17
+ NEW YORK NY 10022
+ US
+
+D4-7C-44 (hex) Huaqin Telecom Technology Co.,Ltd.
+D00000-DFFFFF (base 16) Huaqin Telecom Technology Co.,Ltd.
+ Building 1,No.399, Keyuan Road, Pudong, Shanghai China
+ Shanghai 200120
CN
-9C-43-1E (hex) Symfun Telecom Ltd
-100000-1FFFFF (base 16) Symfun Telecom Ltd
- Floor 4 Building 11 Xi Qi Dian Jia Yuan
- Beijing 100083
+D4-7C-44 (hex) OMRON SENTECH CO., LTD.
+300000-3FFFFF (base 16) OMRON SENTECH CO., LTD.
+ 9F, Ebina Prime Tower, 9-50, Chuo 2 Chome
+ Ebina-City Kanagawa 243-0432
+ JP
+
+88-5D-90 (hex) Private
+F00000-FFFFFF (base 16) Private
+
+B4-4B-D6 (hex) Taizhou convergence Information technology Co.,LTD
+700000-7FFFFF (base 16) Taizhou convergence Information technology Co.,LTD
+ Room 1006,general chamber of commerce,159 henghu road
+ wenling zhejiang 317515
CN
-9C-43-1E (hex) Antailiye Technology Co.,Ltd
-000000-0FFFFF (base 16) Antailiye Technology Co.,Ltd
- 7/F,Zhengjiyuan Buiding,2 Road,Qianjing, Xixiang, Baoan District,Shenzhen
- SHEN ZHEN GUANGDONG 518000
+B4-4B-D6 (hex) Shenzhen Cudy Technology Co., Ltd.
+200000-2FFFFF (base 16) Shenzhen Cudy Technology Co., Ltd.
+ The Great Wall Building,No3 Kefa Road
+ Shenzhen Guangdong 518000
CN
-9C-43-1E (hex) ST Access Control System Corp.
-A00000-AFFFFF (base 16) ST Access Control System Corp.
- 3F., No. 111 Zhongzheng Rd., Banciao Dist., New Taipei City
- New Taipei City 22054
- TW
+B4-4B-D6 (hex) Arnouse Digital Devices Corp
+800000-8FFFFF (base 16) Arnouse Digital Devices Corp
+ 1983 Marcus Ave, Suite 104
+ Lake Success NY 11042
+ US
-C4-FF-BC (hex) Mobiletron Electronics Co., Ltd
-200000-2FFFFF (base 16) Mobiletron Electronics Co., Ltd
- 85, Sec.4, Chung-Ching Rd., Ta-Ya District
- Taichung 428
- TW
+B4-4B-D6 (hex) CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD.
+E00000-EFFFFF (base 16) CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD.
+ 618-2# Gongren West Road,Jiaojiang,
+ Taizhou Zhejiang 317700
+ CN
-C4-FF-BC (hex) iMageTech CO.,LTD.
-400000-4FFFFF (base 16) iMageTech CO.,LTD.
- 5F., No.16, Lane 15, Sec. 6, Mincyuan E. Rd., Neihu District,
- TAIPEI 114
- TW
+B4-4B-D6 (hex) Impakt S.A.
+C00000-CFFFFF (base 16) Impakt S.A.
+ Stanislawa Lema 16
+ Mosina Wielkopolska 62-050
+ PL
-C4-FF-BC (hex) KAGA ELECTRONICS CO.,LTD.
-B00000-BFFFFF (base 16) KAGA ELECTRONICS CO.,LTD.
- 20 Kandamatsunaga-cho
- Chiyoda-ku TOKYO 101-8627
- JP
+3C-42-7E (hex) GJS Co., Ltd.
+700000-7FFFFF (base 16) GJS Co., Ltd.
+ 305, Qianhai Innovation and Entrepreneur Hub, Bldg. C Qianwan 1st Rd., Nanshan District
+ Shenzhen Guangdong 518000
+ CN
-C4-FF-BC (hex) comtime GmbH
-500000-5FFFFF (base 16) comtime GmbH
- Gutenbergring 22
- Norderstedt 22848
- US
+34-04-9E (hex) Private
+900000-9FFFFF (base 16) Private
-DC-E5-33 (hex) Tintel Hongkong Co.Ltd
-B00000-BFFFFF (base 16) Tintel Hongkong Co.Ltd
- FLAT C,23/F,LUCKY PLAZA,315-321 LOCKHART ROAD,WANCHAI,HONGKONG
- HONGKONG GUANG DONG PROVINCE 999077
- HK
+3C-42-7E (hex) Teknoware Oy
+400000-4FFFFF (base 16) Teknoware Oy
+ Ilmarisentie 8
+ Lahti 15200
+ FI
-DC-E5-33 (hex) JB-Lighting Lichtanlagen GmbH
-800000-8FFFFF (base 16) JB-Lighting Lichtanlagen GmbH
- Sallersteig 15
- 89134 89134
- DE
+3C-42-7E (hex) Geoplan Korea
+500000-5FFFFF (base 16) Geoplan Korea
+ Simin-ro 327-7 DaeMyung Bldg #614
+ AnYang 15044
+ KR
-DC-E5-33 (hex) Giant Power Technology Biomedical Corporation
-E00000-EFFFFF (base 16) Giant Power Technology Biomedical Corporation
- Rm201, 2nd Educational Building, No. 84, Gongzhuan Rd, Taishan Dist
- New Taipei City 24301
- TW
+A0-19-B2 (hex) SZBROAD TECHNOLOGY (HK) CO.,LTMITED
+500000-5FFFFF (base 16) SZBROAD TECHNOLOGY (HK) CO.,LTMITED
+ FLAT/RM 5 BLK B 14/F WAH HEN COMMERCIAL CENTRE
+ 383 HENNESSY ROAD WANCHAI Hong Kong 00000
+ HK
-DC-E5-33 (hex) shenzhen bangying electronics co,.ltd
-400000-4FFFFF (base 16) shenzhen bangying electronics co,.ltd
- 3/F Building 16,Hongfa industrialPark,Tangtou Shiyan Town
- shenzhen guangdong 518000
+3C-42-7E (hex) Privacy Labs
+C00000-CFFFFF (base 16) Privacy Labs
+ 10400 NE 4th Street, 7th Floor
+ Bellevue WA 98004
+ US
+
+3C-42-7E (hex) Grandway Technology (Shenzhen) Limited
+000000-0FFFFF (base 16) Grandway Technology (Shenzhen) Limited
+ Block 7, Zhu Keng Industrial Zone
+ Ping Shan District Shenzhen 518118
CN
-A4-DA-22 (hex) AURANEXT
-600000-6FFFFF (base 16) AURANEXT
- 202 quai de clichy
- CLICHY 92110
- FR
+04-C3-E6 (hex) SHANTOU YINGSHENG IMPORT & EXPORT TRADING CO.,LTD.
+C00000-CFFFFF (base 16) SHANTOU YINGSHENG IMPORT & EXPORT TRADING CO.,LTD.
+ Chenghua Industrial Zone,Wenguan Road,Chenghai District
+ Shantou City Guangdong 515800
+ CN
-A4-DA-22 (hex) Wyze Labs Inc
-200000-2FFFFF (base 16) Wyze Labs Inc
- 22522 29TH DR SE L101
- BOTHELL WA 98021
- US
+04-C3-E6 (hex) Invasys
+500000-5FFFFF (base 16) Invasys
+ Sochorova 36
+ Brno 616 00
+ CZ
-A4-DA-22 (hex) LORIOT AG
-400000-4FFFFF (base 16) LORIOT AG
- Zuercherstrasse 68
- Thalwil Zürich 8800
- CH
+04-C3-E6 (hex) Shenzhen Shuotian Information Technology Co., LTD
+600000-6FFFFF (base 16) Shenzhen Shuotian Information Technology Co., LTD
+ Xixiang Street , Bao'an District
+ Shenzhen Guangdong 518000
+ CN
-A4-DA-22 (hex) DURATECH Enterprise,LLC
-300000-3FFFFF (base 16) DURATECH Enterprise,LLC
- NO.1013,184,Gasan digital 2-ro,Geumcheon-gu,Seoul
- Seoul 08501
- KR
+04-C3-E6 (hex) Flintec UK Ltd.
+B00000-BFFFFF (base 16) Flintec UK Ltd.
+ W4/5 Capital Point, Wentloog Avenue
+ Cardiff Cardiff CF3 2PW
+ GB
-A4-DA-22 (hex) EHO.LINK
-C00000-CFFFFF (base 16) EHO.LINK
- 5 Avenue de Saint Menet, Imm. Axiome, Bat. B
- Marseille 13011
- FR
+04-C3-E6 (hex) Sealed Unit Parts Co., Inc.
+A00000-AFFFFF (base 16) Sealed Unit Parts Co., Inc.
+ 2230 Landmark Place
+ ALLENWOOD NJ 08720
+ US
-A4-DA-22 (hex) General Electric Company
-000000-0FFFFF (base 16) General Electric Company
- Valle del Cedro #1551
- Ciudad Juarez Chih 32575
- MX
+C0-83-59 (hex) ista International GmbH
+800000-8FFFFF (base 16) ista International GmbH
+ Luxemburger Strasse 1
+ Essen NRW 45131
+ DE
-88-A9-A7 (hex) Mikroelektronika
-300000-3FFFFF (base 16) Mikroelektronika
- Batajnicki drum 23
- Belgrade 11186
- RS
+3C-42-7E (hex) Compal Electronics INC.
+B00000-BFFFFF (base 16) Compal Electronics INC.
+ No.8 , Nandong Road , PingZhen Dist.
+ Taoyuan Taiwan 32455
+ TW
-88-A9-A7 (hex) kimura giken corporation
-700000-7FFFFF (base 16) kimura giken corporation
- 4-9-19 kamiyoga
- Setagaya-ku Tokyo 158-0098
- JP
+C0-83-59 (hex) Beijing Cloud Fly Technology Development Co.Ltd
+600000-6FFFFF (base 16) Beijing Cloud Fly Technology Development Co.Ltd
+ No. 1703, Zhong An Sheng Ye Building, No. 168 Bei Yuan Road, Chaoyang District, Beijing
+ Beijing Beijing 100101
+ CN
-88-A9-A7 (hex) FlashForge Corporation
-900000-9FFFFF (base 16) FlashForge Corporation
- No.518, Xianyuan Road
- Jinhua Zhejiang 321000
+9C-F6-DD (hex) Shanxi ZhuoZhi fei High Electronic Technology Co. Ltd.
+E00000-EFFFFF (base 16) Shanxi ZhuoZhi fei High Electronic Technology Co. Ltd.
+ Red flag East Street
+ yuncheng shanxi 044000
CN
-88-A9-A7 (hex) Thomas & Darden, Inc
-400000-4FFFFF (base 16) Thomas & Darden, Inc
- 916 Springdale Rd Bldg 4 #104
- Austin 78702
+30-09-F9 (hex) Technology for Humankind
+D00000-DFFFFF (base 16) Technology for Humankind
+ 3913 N. Rushwood St.
+ Wichita KS 67226
US
-88-A9-A7 (hex) Impact Distribution
-E00000-EFFFFF (base 16) Impact Distribution
- Ter Heidelaan 50a
- Aarschot 3200
- BE
+30-09-F9 (hex) Shenzhen Sunvell Electronics Co., Ltd.
+100000-1FFFFF (base 16) Shenzhen Sunvell Electronics Co., Ltd.
+ 5th Floor, Building F, Hongzhu Yongqi Technology Park, Lezhujiao Village, Xixiang Town, Bao’ an District,
+ Shenzhen GuangDong 518000
+ CN
-88-A9-A7 (hex) Honeywell spol. s.r.o. HTS CZ o.z.
-200000-2FFFFF (base 16) Honeywell spol. s.r.o. HTS CZ o.z.
- Turanka 100/1387
- Brno 62700
- CZ
+30-09-F9 (hex) Bonraybio
+900000-9FFFFF (base 16) Bonraybio
+ 4F., No.118, Gongye 9th Rd., Dali Dist.,
+ Taichung City Taiwan 412
+ TW
-88-A9-A7 (hex) Solaredge LTD.
-100000-1FFFFF (base 16) Solaredge LTD.
- Hamada 1
- Herzelia 4673335
- IL
+30-09-F9 (hex) Sichuan Nebula Networks Co.,LTD.
+B00000-BFFFFF (base 16) Sichuan Nebula Networks Co.,LTD.
+ Floor 21 Building 2,No.200 Tianquan Road,West Hi-Tech Zone,
+ Chengdu Sichuan 611731
+ CN
-F0-41-C8 (hex) Candelic Limited
-400000-4FFFFF (base 16) Candelic Limited
- Unit 312, 3/F Solo Workshop, 131-132 Cannaught Road West
- Hong Kong 111111
+30-09-F9 (hex) OOO Microlink-Svyaz
+300000-3FFFFF (base 16) OOO Microlink-Svyaz
+ 1st veshnjakovsky proezd 7
+ moscow moscow 109456
+ RU
+
+84-89-EC (hex) Arts Digital Technology (HK) Ltd.
+800000-8FFFFF (base 16) Arts Digital Technology (HK) Ltd.
+ 1704, 17/F, Fo Tan Industrial Centre, 26-28 Au Pui Wan Street, Fo Tan, Hong Kong
+ Hong Kong Nil
HK
-F0-41-C8 (hex) POSTIUM KOREA CO., LTD.
-800000-8FFFFF (base 16) POSTIUM KOREA CO., LTD.
- A208 Samsong Techno Valley, 140 Tongil-ro, Deogyang-gu
- Koyang-si Kyeonggi-do 10594
- KR
+84-89-EC (hex) Aerionics Inc.
+300000-3FFFFF (base 16) Aerionics Inc.
+ 3601 N St Paul Avenue
+ Sioux Falls SD 57104
+ US
-88-5F-E8 (hex) Beijing laiwei Technology Co.,Ltd
-400000-4FFFFF (base 16) Beijing laiwei Technology Co.,Ltd
- Room 205,2/F,No.1 Fazhan Road Beijing information international base Huilongguan town Changping district Beijing
- Beijing Beijing 102206
+A0-28-33 (hex) Shanghai Nohmi Secom Fire Protection Equipment Co.,Ltd.
+200000-2FFFFF (base 16) Shanghai Nohmi Secom Fire Protection Equipment Co.,Ltd.
+ No.98,Lane 1971,(s)Lianhua Road,Minhang Area
+ Shanghai Shanghai 201108
CN
-88-5F-E8 (hex) Shenzhen Xin Kingbrand Enterprises Co.,Ltd
-600000-6FFFFF (base 16) Shenzhen Xin Kingbrand Enterprises Co.,Ltd
- KingBrand Industrial Zone, Nanpu Road,Shang Liao Lin Pikeng,Shajing Town,Baoan District
- Shenzhen 518000
- CN
+84-89-EC (hex) Zephyr Engineering, Inc.
+500000-5FFFFF (base 16) Zephyr Engineering, Inc.
+ 2412 W. Huntington Dr.
+ Tempe AZ 85282
+ US
-48-0B-B2 (hex) annapurnalabs
-600000-6FFFFF (base 16) annapurnalabs
- HACRMEL 2 st Brosh BLDG FLOOR3
- YOKNEAM. POB 218 Israel 26814
- IL
+A0-28-33 (hex) GERSYS GmbH
+000000-0FFFFF (base 16) GERSYS GmbH
+ Hans-Urmiller-Ring 12A
+ Wolfratshausen 82515
+ DE
-48-0B-B2 (hex) BAJA ELECTRONICS TECHNOLOGY LIMITED
-100000-1FFFFF (base 16) BAJA ELECTRONICS TECHNOLOGY LIMITED
- 403, Unit 3, Building 3, Zhongdian Hi-Tech Park, No.1 Kejiqi Rd.
- Zhuhai Guangdong 519080
+A0-28-33 (hex) HZHY TECHNOLOGY
+800000-8FFFFF (base 16) HZHY TECHNOLOGY
+ The 2th floor,Longzeyuan Multi-use
+ beijing 102208
CN
-0C-73-EB (hex) Dinkle Enterprise Co., Ltd.
-700000-7FFFFF (base 16) Dinkle Enterprise Co., Ltd.
- No.19, Wuquan 2nd Rd., Wugu Dist.
- New Taipei City 24890
- TW
+A0-28-33 (hex) Firm INFORMTEST Ltd.
+400000-4FFFFF (base 16) Firm INFORMTEST Ltd.
+ APT. 8, LODG. XIV ,FL.6, bld.4, Passage Savelkinsky
+ Zelenograd Moscow 124482
+ RU
-3C-24-F0 (hex) COMATIS
-B00000-BFFFFF (base 16) COMATIS
- 8 rue Carnot
- SAINT-CYR-L'ECOLE 78210
- FR
+A0-28-33 (hex) FlexLink AB
+B00000-BFFFFF (base 16) FlexLink AB
+ BYFOGDEGATAN 11
+ GOTEBORG 41505
+ SE
-8C-1C-DA (hex) Septentrio NV
-500000-5FFFFF (base 16) Septentrio NV
- Interleuvenlaan 15i
- Leuven 3001
- BE
+A4-ED-43 (hex) Shanghai Facom Electronics Technology Co, ltd.
+600000-6FFFFF (base 16) Shanghai Facom Electronics Technology Co, ltd.
+ The third floor, A area, Huaxu road No. 685
+ Shanghai Xujing town,Qingpu 200217
+ CN
-80-E4-DA (hex) Private
+DC-44-27 (hex) Private
F00000-FFFFFF (base 16) Private
-74-19-F8 (hex) Private
+1C-21-D1 (hex) Private
F00000-FFFFFF (base 16) Private
-2C-48-35 (hex) Newtrax Technologies Inc
-300000-3FFFFF (base 16) Newtrax Technologies Inc
- 360 St-Jacques, Floor 8
- Montreal Quebec H2Y 1P5
- CA
-
-BC-34-00 (hex) Private
+C8-8E-D1 (hex) Private
F00000-FFFFFF (base 16) Private
-74-F8-DB (hex) Ballard Technology, Inc,
-A00000-AFFFFF (base 16) Ballard Technology, Inc,
- 11400 Airport Rd
- Everett Wa 98204
- US
-
-2C-48-35 (hex) IROOTECH TECHNOLOGY CO.,LTD
-E00000-EFFFFF (base 16) IROOTECH TECHNOLOGY CO.,LTD
- Room 606, Floor 6, Building 5, Eastern Yard 10, Xibeiwang East Road
- Beijing 100092
- CN
-
-A0-19-B2 (hex) MIS Industrie Systeme GmbH & Co. KG
-800000-8FFFFF (base 16) MIS Industrie Systeme GmbH & Co. KG
- Lohwiese 7
- Scheuring Bavaria 86937
- DE
-
1C-87-76 (hex) Hekatron Vertriebs GmbH
B00000-BFFFFF (base 16) Hekatron Vertriebs GmbH
Brühlmatten 9
@@ -7793,12 +8366,6 @@ A00000-AFFFFF (base 16) SECAD SA
Beijing Beijing 100001
CN
-38-FD-FE (hex) B.U.G.SST,Inc
-200000-2FFFFF (base 16) B.U.G.SST,Inc
- 1-15 Kagurazaka,Shinjyukuku,
- Tokyo 162-0825
- JP
-
5C-F2-86 (hex) Shenzhen VST Automotive Electronics Co., LTD
900000-9FFFFF (base 16) Shenzhen VST Automotive Electronics Co., LTD
3 floor,1Building, No.3 West of ShangXue Science and technology park, Bantian town, LongGang District
@@ -8183,9 +8750,6 @@ C00000-CFFFFF (base 16) Swisson AG
Lyss 3250
CH
-74-E1-4A (hex) Private
-F00000-FFFFFF (base 16) Private
-
B8-D8-12 (hex) Private
F00000-FFFFFF (base 16) Private
@@ -8513,9 +9077,6 @@ B00000-BFFFFF (base 16) Q Core Medical Ltd
Netanya 4250529
IL
-F0-23-B9 (hex) Private
-D00000-DFFFFF (base 16) Private
-
F0-23-B9 (hex) Xiamen Jinhaode Electronic Co.,Ltd
600000-6FFFFF (base 16) Xiamen Jinhaode Electronic Co.,Ltd
2003# Fuyu Build, Changqing Road 536, Siming
@@ -8546,9 +9107,6 @@ D00000-DFFFFF (base 16) UnaliWear, Inc.
Austin TX 78703
US
-A0-C5-F2 (hex) Private
-000000-0FFFFF (base 16) Private
-
A0-C5-F2 (hex) Synapsys Solutions Ltd.
E00000-EFFFFF (base 16) Synapsys Solutions Ltd.
1 Woodlands Court, Albert Drive
@@ -8627,9 +9185,6 @@ D00000-DFFFFF (base 16) SIGMA-ELEKTRO GmbH
Dongguan 523041
CN
-74-F8-DB (hex) Private
-F00000-FFFFFF (base 16) Private
-
7C-BA-CC (hex) ALPHA TECHNOLOGIES, LLC
E00000-EFFFFF (base 16) ALPHA TECHNOLOGIES, LLC
3030 GILCHRIST ROAD
@@ -8672,12 +9227,6 @@ E00000-EFFFFF (base 16) ALPHA TECHNOLOGIES, LLC
Chicago IL 60611
US
-58-FC-DB (hex) Private
-F00000-FFFFFF (base 16) Private
-
-BC-66-41 (hex) Private
-F00000-FFFFFF (base 16) Private
-
34-00-8A (hex) Hibertek International Limited
A00000-AFFFFF (base 16) Hibertek International Limited
Rm. 6, 21F., NO.5, Sec.3, New Taipei Blvd., Xinzhuang Dist.
@@ -8720,9 +9269,6 @@ E00000-EFFFFF (base 16) ARC Technology Co., Ltd
Champaign IL 61820
US
-E4-95-6E (hex) Private
-F00000-FFFFFF (base 16) Private
-
18-9B-A5 (hex) Taiwan Name Plate Co.,LTD
E00000-EFFFFF (base 16) Taiwan Name Plate Co.,LTD
No.36, Huaya 1st Rd., Guishan Dist., Taoyuan City 33383, Taiwan
@@ -8966,6 +9512,9 @@ B00000-BFFFFF (base 16) Shanghai Visteon Automotive Electronics System CO.
Chicago IL 60607
US
+F0-23-B9 (hex) Private
+D00000-DFFFFF (base 16) Private
+
34-D0-B8 (hex) Kongqiguanjia (Beijing)Technology co.,ltd
E00000-EFFFFF (base 16) Kongqiguanjia (Beijing)Technology co.,ltd
Room 1201,Block A,Building of Fesco,Xidawang Road,Chaoyang district
@@ -9134,9 +9683,6 @@ B00000-BFFFFF (base 16) Popit Oy
Shenzhen Guangdong 518000
CN
-58-E8-76 (hex) Private
-000000-0FFFFF (base 16) Private
-
38-B8-EB (hex) Private
700000-7FFFFF (base 16) Private
@@ -9149,6 +9695,210 @@ F00000-FFFFFF (base 16) Private
34-04-9E (hex) Private
C00000-CFFFFF (base 16) Private
+A0-19-B2 (hex) GfG mbH
+600000-6FFFFF (base 16) GfG mbH
+ Kloennestrasse 99
+ Dortmund 44143
+ DE
+
+A0-19-B2 (hex) Vast Production Services
+000000-0FFFFF (base 16) Vast Production Services
+ 307 Robbins Drive
+ Troy MI 48083
+ US
+
+74-F8-DB (hex) Private
+F00000-FFFFFF (base 16) Private
+
+D4-7C-44 (hex) LS Communication Co.,Ltd.
+500000-5FFFFF (base 16) LS Communication Co.,Ltd.
+ LS Bldg., Hwachang-ro, 95(Seoksoo-dong), Manan-gu
+ Anyang-city Gyeonggi-do 13905
+ KR
+
+D4-7C-44 (hex) SHENZHEN ANYSEC TECHNOLOGY CO. LTD
+E00000-EFFFFF (base 16) SHENZHEN ANYSEC TECHNOLOGY CO. LTD
+ 601, 1 BUILDING,MeiLin Dolly Industrial Zone,Futian District
+ SHENZHEN GuangDong 518000
+ CN
+
+B4-4B-D6 (hex) Huizhou Sunoda Technology Co. Ltd
+300000-3FFFFF (base 16) Huizhou Sunoda Technology Co. Ltd
+ NO.4 XING JU WEST ROAD,DONG XING DISTRICT,ZHONG KAI DONG JIANG HIGH TECHNOLOGY INDUSTRIAL PARK,
+ HUI ZHOU guangdong 516000
+ CN
+
+A0-C5-F2 (hex) Quantlab Financial, LLC
+000000-0FFFFF (base 16) Quantlab Financial, LLC
+ 3 Greenway Plaza, Suite 200
+ 3 Greenway Plaza TX 77046
+ US
+
+3C-42-7E (hex) snap40 Ltd
+A00000-AFFFFF (base 16) snap40 Ltd
+ 24 Forth Street
+ Edinburgh EH1 3LH
+ GB
+
+04-C3-E6 (hex) Ekin Teknoloji San ve Tic A.S.
+900000-9FFFFF (base 16) Ekin Teknoloji San ve Tic A.S.
+ maden mah. gediz. sok. no:7, sariyer
+ istanbul 34450
+ TR
+
+04-C3-E6 (hex) Guangdong New Pulse Electric Co., Ltd.
+100000-1FFFFF (base 16) Guangdong New Pulse Electric Co., Ltd.
+ No. 38 South Kemu Road
+ Guangzhou City Tianhe District, Guangdong Province 510520
+ CN
+
+04-C3-E6 (hex) SLOC GmbH
+800000-8FFFFF (base 16) SLOC GmbH
+ Nikolaiplatz 4
+ Graz Styria 8020
+ AT
+
+04-C3-E6 (hex) Innovusion Inc.
+400000-4FFFFF (base 16) Innovusion Inc.
+ 4920 El Camino Real
+ Los Altos CA 94022
+ US
+
+04-C3-E6 (hex) Amiosec Ltd
+D00000-DFFFFF (base 16) Amiosec Ltd
+ Unit 5 Miller Court
+ Tewkesbury Gloucestershire GL20 8DN
+ GB
+
+C0-83-59 (hex) Fuzhou Fdlinker Technology Co.,LTD
+700000-7FFFFF (base 16) Fuzhou Fdlinker Technology Co.,LTD
+ 28th floor, Building 1, area F, Fuzhou software park, 89 Ruanjian Avenue
+ Fuzhou Fujian 350001
+ CN
+
+C0-83-59 (hex) Huaxin SM Optics Co. LTD.
+200000-2FFFFF (base 16) Huaxin SM Optics Co. LTD.
+ 5F,B8,Tianfu software Park,Tianfu Road
+ Chengdu Sichuan 610041
+ CN
+
+C0-83-59 (hex) CHONGQING JIUYU SMART TECHNOLOGY CO.LTD.
+000000-0FFFFF (base 16) CHONGQING JIUYU SMART TECHNOLOGY CO.LTD.
+ T2-11-3, No. 2 Jiangbeizui Financial City, Jiangbei District,
+ Chongqing Chongqing 400000
+ CN
+
+58-FC-DB (hex) Private
+F00000-FFFFFF (base 16) Private
+
+C0-83-59 (hex) Gardner Denver Thomas GmbH
+D00000-DFFFFF (base 16) Gardner Denver Thomas GmbH
+ Livry-Gargan-Straße 10
+ Fürstenfeldbruck Bavaria 82256
+ DE
+
+BC-66-41 (hex) Private
+F00000-FFFFFF (base 16) Private
+
+9C-F6-DD (hex) CAMA(Luoyang)Electronics Co.,Ltd
+900000-9FFFFF (base 16) CAMA(Luoyang)Electronics Co.,Ltd
+ Luoyang High-tech District, Chuncheng Road 16th.
+ Luoyang Henan 471003
+ CN
+
+9C-F6-DD (hex) RYEEX Technology Co.,Ltd.
+300000-3FFFFF (base 16) RYEEX Technology Co.,Ltd.
+ RM106,Joinin Hub,Builing J District 71,Construction Industrial Park,Xin'an Street,Bao'an, Shenzhen,China
+ SHENZHEN GUANGDONG 518101
+ CN
+
+9C-F6-DD (hex) Capital Engineering & Research Incorporation Ltd.
+400000-4FFFFF (base 16) Capital Engineering & Research Incorporation Ltd.
+ NO.7 JianAnJie, Beijing Economic-Technological Development Area
+ Beijing 100176
+ CN
+
+9C-F6-DD (hex) Beijing Sifang Automation Co., Ltd.
+200000-2FFFFF (base 16) Beijing Sifang Automation Co., Ltd.
+ No.9,Shangdi 4th Street,Haidian District
+ Beijing 100085
+ CN
+
+30-09-F9 (hex) Hurray Cloud Technology Co., Ltd.
+000000-0FFFFF (base 16) Hurray Cloud Technology Co., Ltd.
+ 7F., No.407, Sec. 2, Zhongshan Rd., Zhonghe Dist.,
+ New Taipei City 235
+ TW
+
+58-E8-76 (hex) Private
+000000-0FFFFF (base 16) Private
+
+84-89-EC (hex) Research Electronics International, LLC.
+100000-1FFFFF (base 16) Research Electronics International, LLC.
+ 455 Secuity Drive
+ Cookeville TN 38506
+ US
+
+30-09-F9 (hex) ZhongLi HengFeng (Shenzhen) Technology co.,Ltd.
+E00000-EFFFFF (base 16) ZhongLi HengFeng (Shenzhen) Technology co.,Ltd.
+ Room 402C Donglian Buiding,Chuangye NO 2 road,Baoan
+ Shenzhen Guangdong 430000
+ CN
+
+8C-1C-DA (hex) Riegl Laser Measurement Systems GmbH
+D00000-DFFFFF (base 16) Riegl Laser Measurement Systems GmbH
+ Riedenburgstraße 48
+ Horn Niederösterreich A-3580
+ AT
+
+84-89-EC (hex) Vayyar Imaging Ltd.
+400000-4FFFFF (base 16) Vayyar Imaging Ltd.
+ 3 Avraham Giron St
+ Yehud 5621717
+ IL
+
+84-89-EC (hex) Shenzhen Xtooltech Co., Ltd
+900000-9FFFFF (base 16) Shenzhen Xtooltech Co., Ltd
+ 10574 Acacia St, Suite D4
+ Rancho Cucamonga CA 91730
+ US
+
+84-89-EC (hex) BYDA Co. Ltd.,
+700000-7FFFFF (base 16) BYDA Co. Ltd.,
+ 4F, KNS Bldg., 8, Gaepo-ro 25 gil, Gangnam-gu
+ Seoul 06306
+ KR
+
+84-89-EC (hex) SmartGiant Technology
+000000-0FFFFF (base 16) SmartGiant Technology
+ 1 North Zhong Jia Zhuang, Shi Gang Dong, Da Long Street
+ Guangzhou Guangdong 510000
+ CN
+
+A0-28-33 (hex) Kalray S.A.
+C00000-CFFFFF (base 16) Kalray S.A.
+ 180 avenue de l’Europe
+ Montbonnot Saint Martin 38330
+ FR
+
+38-FD-FE (hex) Smart Solution Technology, Inc
+200000-2FFFFF (base 16) Smart Solution Technology, Inc
+ 1-15 Kagurazaka,Shinjyukuku,
+ Tokyo 162-0825
+ JP
+
+A0-28-33 (hex) Kryptus Information Security S/A
+700000-7FFFFF (base 16) Kryptus Information Security S/A
+ Av Romeu Tórtima, 554
+ Campinas São Paulo 13084-791
+ BR
+
+E4-95-6E (hex) Private
+F00000-FFFFFF (base 16) Private
+
+74-E1-4A (hex) Private
+F00000-FFFFFF (base 16) Private
+
1C-87-74 (hex) Philips Personal Health Solutions
000000-0FFFFF (base 16) Philips Personal Health Solutions
High Tech Campus, HTC37 floor 0
@@ -10766,9 +11516,6 @@ D00000-DFFFFF (base 16) Beijing Xinxunxintong Eletronics Co.,Ltd
Beijing 100192
CN
-8C-C8-F4 (hex) Private
-700000-7FFFFF (base 16) Private
-
8C-C8-F4 (hex) ITECH Electronic Co.,ltd.
400000-4FFFFF (base 16) ITECH Electronic Co.,ltd.
No.108, XiShanqiao Nanlu
@@ -11099,12 +11846,6 @@ D00000-DFFFFF (base 16) THK Co.,LTD.
Changsha Hunan 410000
CN
-14-1F-BA (hex) Private
-F00000-FFFFFF (base 16) Private
-
-B4-37-D1 (hex) Private
-F00000-FFFFFF (base 16) Private
-
7C-BA-CC (hex) Fossil Power Systems Inc
600000-6FFFFF (base 16) Fossil Power Systems Inc
10 Mosher Drive
@@ -11141,9 +11882,6 @@ B00000-BFFFFF (base 16) Maddalena S.p.A.
Drammen Buskerud 3036
NO
-78-C2-C0 (hex) Private
-F00000-FFFFFF (base 16) Private
-
28-F5-37 (hex) Performance Motion Devices
E00000-EFFFFF (base 16) Performance Motion Devices
1 Technology Park Drive
@@ -11156,9 +11894,6 @@ E00000-EFFFFF (base 16) Performance Motion Devices
Shenzhen Guangdong 518000
CN
-98-6D-35 (hex) Private
-900000-9FFFFF (base 16) Private
-
34-00-8A (hex) Globex 99 LTD
300000-3FFFFF (base 16) Globex 99 LTD
Trakia bl. 240
@@ -11374,3 +12109,210 @@ F0-AC-D7 (hex) Sercomm Corporation.
54-9A-11 (hex) Private
F00000-FFFFFF (base 16) Private
+
+A0-19-B2 (hex) RYD Electronic Technology Co.,Ltd.
+D00000-DFFFFF (base 16) RYD Electronic Technology Co.,Ltd.
+ Room1602,No68 Taidong Road,Siming District,Xiamen City
+ Xiamen FuJian 361000
+ CN
+
+A0-19-B2 (hex) Osatec
+400000-4FFFFF (base 16) Osatec
+ 15 Parkovaya
+ Moscow 105203
+ WS
+
+A0-19-B2 (hex) HangZhou iMagic Technology Co., Ltd
+B00000-BFFFFF (base 16) HangZhou iMagic Technology Co., Ltd
+ Block F, 11th Floor, Building A, Tiantang Software Park, 3# Xidoumen Road,
+ Hangzhou Zhejiang 310012
+ CN
+
+8C-C8-F4 (hex) Private
+700000-7FFFFF (base 16) Private
+
+D4-7C-44 (hex) OPTiM Corporation
+B00000-BFFFFF (base 16) OPTiM Corporation
+ 1 Honjo-machi
+ Saga 840-8502
+ JP
+
+D4-7C-44 (hex) Tendzone International Pte Ltd
+A00000-AFFFFF (base 16) Tendzone International Pte Ltd
+ Rm 202, Blk C, Huahan Innovation Park, No.16 Langshan Rd,Nanshan District
+ Shenzhen GuangDong 518057
+ CN
+
+D4-7C-44 (hex) Pongee Industries Co., Ltd.
+700000-7FFFFF (base 16) Pongee Industries Co., Ltd.
+ 5F., No.738, Chung-Cheng Road,
+ Chung-Ho District, New Taipei City, 23511
+ TW
+
+14-1F-BA (hex) Private
+F00000-FFFFFF (base 16) Private
+
+D4-7C-44 (hex) Beijing Maystar Information Technology Co., Ltd.
+800000-8FFFFF (base 16) Beijing Maystar Information Technology Co., Ltd.
+ Building B 5/F,Shangdi Keji Zonghe Building,No.22 Shangdi Information Road, Haidian District
+ Beijing 100084
+ CN
+
+D4-7C-44 (hex) Sammi Onformation Systems
+400000-4FFFFF (base 16) Sammi Onformation Systems
+ Gasan Digital 1-ro 212
+ Geumcheon-gu Seoul 08502
+ KR
+
+B4-4B-D6 (hex) Qstar Technology Co,Ltd
+900000-9FFFFF (base 16) Qstar Technology Co,Ltd
+ 311# Xindongxing Business Centre ,2rd Road liuxian ,Bao'an Shenzhen China
+ Shenzhen Guangdong 518100
+ CN
+
+B4-4B-D6 (hex) ELLETA SOLUTIONS LTD
+D00000-DFFFFF (base 16) ELLETA SOLUTIONS LTD
+ Yetsi'at Eropa Street 20
+ Hadera 3848427
+ IL
+
+B4-4B-D6 (hex) DongYoung media
+B00000-BFFFFF (base 16) DongYoung media
+ #18, Dangjeong-Ro, Gunpo-Si,
+ Gyeonggi-Do, 15849
+ KR
+
+3C-42-7E (hex) TAITEX CORPORATION
+900000-9FFFFF (base 16) TAITEX CORPORATION
+ 1-7-12,WAKATAKE
+ ICHINOMIYA-SHI AICHI-KEN 491-0832
+ JP
+
+B4-37-D1 (hex) Private
+F00000-FFFFFF (base 16) Private
+
+98-6D-35 (hex) Private
+900000-9FFFFF (base 16) Private
+
+3C-42-7E (hex) Starloop Tech Co., Ltd.
+200000-2FFFFF (base 16) Starloop Tech Co., Ltd.
+ #643, Meinian Plaza A
+ Chengdu 610000
+ CN
+
+D4-7C-44 (hex) Suzhou Wan Dian Zhang Network Technology Co., Ltd
+900000-9FFFFF (base 16) Suzhou Wan Dian Zhang Network Technology Co., Ltd
+ No. 209 Zhuyuan Road, High-tech Zone
+ Suzhou City Jiangsu 215010
+ CN
+
+3C-42-7E (hex) Edit Srl
+600000-6FFFFF (base 16) Edit Srl
+ Via Grotte di Nottola 10
+ Cisterna di Latina Latina 04012
+ IT
+
+3C-42-7E (hex) Shenzhen VETAS Communication Technology Co , Ltd.
+300000-3FFFFF (base 16) Shenzhen VETAS Communication Technology Co , Ltd.
+ Room 1301-1303,West Wing,Skyworth Semiconductor Design Building,No.18,Gaoxin South 4th road, Nanshan District
+ ShenZhen Guangdong 518063
+ CN
+
+04-C3-E6 (hex) SiS Technology
+200000-2FFFFF (base 16) SiS Technology
+ Business Park Varna, building B1, floor 4
+ Varna 9000
+ BG
+
+04-C3-E6 (hex) Advanced Digital Technologies, s.r.o.
+700000-7FFFFF (base 16) Advanced Digital Technologies, s.r.o.
+ Purkynova 649/127
+ Medlanky Brno 612 00
+ CZ
+
+78-C2-C0 (hex) Private
+F00000-FFFFFF (base 16) Private
+
+9C-F6-DD (hex) KXT Technology Co., Ltd.
+700000-7FFFFF (base 16) KXT Technology Co., Ltd.
+ 3F. No.42, Sec. 2, Chongsin Rd., Sanchong Dist.
+ New Taipei City 241
+ TW
+
+9C-F6-DD (hex) Shenzhen Xtooltech Co., Ltd
+600000-6FFFFF (base 16) Shenzhen Xtooltech Co., Ltd
+ 10574 Acacia St, Suite D4
+ Rancho Cucamonga CA 91730
+ US
+
+9C-F6-DD (hex) annapurnalabs
+000000-0FFFFF (base 16) annapurnalabs
+ HACRMEL 2 st Brosh BLDG FLOOR3
+ YOKNEAM. POB 218 Israel 26814
+ IL
+
+9C-F6-DD (hex) Guangzhou LANGO Electronics Technology Co., Ltd.
+B00000-BFFFFF (base 16) Guangzhou LANGO Electronics Technology Co., Ltd.
+ 136#, Gaopu Road, Tianhe District
+ Guangzhou Guangdong 510663
+ CN
+
+30-09-F9 (hex) VELSITEC-CLIBASE
+500000-5FFFFF (base 16) VELSITEC-CLIBASE
+ LA RATELIERE
+ SAINT-JUST-MALMONT Haute-Loire 43240
+ FR
+
+9C-F6-DD (hex) AVI Pty Ltd
+A00000-AFFFFF (base 16) AVI Pty Ltd
+ 9 Pitt Way
+ Booragoon Western Australia 6154
+ AU
+
+30-09-F9 (hex) Punkt Tronics AG
+400000-4FFFFF (base 16) Punkt Tronics AG
+ Via Losanna 4
+ Lugano 6900
+ CH
+
+30-09-F9 (hex) essence security
+800000-8FFFFF (base 16) essence security
+ Aba Even 12 st
+ Herzelia 4672530
+ IL
+
+A0-28-33 (hex) Xiamen Caimore Communication Technology Co.,Ltd.
+600000-6FFFFF (base 16) Xiamen Caimore Communication Technology Co.,Ltd.
+ #2 of 302 Unit, 23# Wanghai Road, Xiamen Software Park II
+ Xiamen Fujian 361009
+ CN
+
+A0-28-33 (hex) Medical Evolution Kft
+A00000-AFFFFF (base 16) Medical Evolution Kft
+ Liszenko telep 1
+ Pomaz 2013
+ HU
+
+A0-28-33 (hex) SHANGHAI XUNTAI INFORMATION TECHNOLOGY CO.,LTD.
+300000-3FFFFF (base 16) SHANGHAI XUNTAI INFORMATION TECHNOLOGY CO.,LTD.
+ ET SPACE, ZIZHU PARK, NO.555, DONGCHUAN RD.
+ SHANGHAI SHANGHAI 200241
+ CN
+
+A0-28-33 (hex) Ordercube GmbH
+100000-1FFFFF (base 16) Ordercube GmbH
+ Aßlinger Str. 6
+ Grafing b. München Bayern 85567
+ DE
+
+A4-ED-43 (hex) Beijing ICPC CO.,Ltd.
+500000-5FFFFF (base 16) Beijing ICPC CO.,Ltd.
+ Fengtai District HuaXiang LiuQuan West Road NO.8 Xinhua ShuangChuangYuan Building B Floor 2 NO.203
+ Beijing Beijing 100070
+ CN
+
+A4-ED-43 (hex) Guangzhou Maxfaith Communication Technology Co.,LTD.
+A00000-AFFFFF (base 16) Guangzhou Maxfaith Communication Technology Co.,LTD.
+ 3rd Floor,Office of Youtong Zone,No.139,Zhongshan Avenue
+ Guangzhou 510665
+ CN
diff --git a/hwdb/ma-small.txt b/hwdb/ma-small.txt
index 7d784ccf01..6364a7e1a9 100644
--- a/hwdb/ma-small.txt
+++ b/hwdb/ma-small.txt
@@ -500,12 +500,6 @@ A00000-A00FFF (base 16) ATX NETWORKS LTD
Stockholm n/a 11642
SE
-70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
-5C8000-5C8FFF (base 16) YUYAMA MFG Co.,Ltd
- 3-3-1
- TOYONAKASHI OSAKA 561-0841
- JP
-
70-B3-D5 (hex) Subinitial LLC
D9C000-D9CFFF (base 16) Subinitial LLC
10160 Three Oaks Way
@@ -1634,12 +1628,6 @@ FEB000-FEBFFF (base 16) Les distributions Multi-Secure incorporee
Krakow malopolska 31-989
PL
-70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
-742000-742FFF (base 16) YUYAMA MFG Co.,Ltd
- 3-3-1
- TOYONAKASHI OSAKA 561-0841
- JP
-
70-B3-D5 (hex) Impulse Networks Pte Ltd
493000-493FFF (base 16) Impulse Networks Pte Ltd
1 Raffles Place, #44-08 Raffles Place
@@ -2879,12 +2867,6 @@ BE4000-BE4FFF (base 16) Kunshan excellent Intelligent Technology Co., Ltd.
kunshan Jiangsu Province 215301
CN
-70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
-E86000-E86FFF (base 16) YUYAMA MFG Co.,Ltd
- 3-3-1
- TOYONAKASHI OSAKA 561-0841
- JP
-
70-B3-D5 (hex) QUANTAFLOW
6EB000-6EBFFF (base 16) QUANTAFLOW
AVENUE DU CANADA
@@ -2981,6 +2963,12 @@ FFE000-FFEFFF (base 16) Private
70-B3-D5 (hex) Private
292000-292FFF (base 16) Private
+70-B3-D5 (hex) Metatronics B.V.
+C7D000-C7DFFF (base 16) Metatronics B.V.
+ Torenallee 42-54
+ Eindhoven 5617 BD
+ NL
+
70-B3-D5 (hex) RoboCore Tecnologia
0AC000-0ACFFF (base 16) RoboCore Tecnologia
Estrada das Lagrimas 1986 sala 22
@@ -3023,6 +3011,186 @@ B7F000-B7FFFF (base 16) JSK System
Basel 4054
CH
+70-B3-D5 (hex) Medical Monitoring Center OOD
+92E000-92EFFF (base 16) Medical Monitoring Center OOD
+ Office 8, 10 Poduevo Street
+ Sofia 1680
+ BG
+
+70-B3-D5 (hex) Mettler Toledo Hi Speed
+D64000-D64FFF (base 16) Mettler Toledo Hi Speed
+ 5 Barr Road
+ Ithaca NY 14850
+ US
+
+70-B3-D5 (hex) MICAS AG
+AB3000-AB3FFF (base 16) MICAS AG
+ Turleyring 18-22
+ Oelsnitz 09376
+ DE
+
+70-B3-D5 (hex) INTERNET PROTOCOLO LOGICA SL
+B0B000-B0BFFF (base 16) INTERNET PROTOCOLO LOGICA SL
+ Sector Foresta 43, local 26
+ Tres Cantos Madrid 28760
+ ES
+
+70-B3-D5 (hex) Foxconn 4Tech
+A46000-A46FFF (base 16) Foxconn 4Tech
+ U Zámečku 27
+ Pardubice Česká republika 53003
+ CZ
+
+70-B3-D5 (hex) SOFTCREATE CORP.
+3C7000-3C7FFF (base 16) SOFTCREATE CORP.
+ 2-15-1 Shibuya
+ Shibuya-ku Tokyo 150-0002
+ JP
+
+70-B3-D5 (hex) TripleOre
+862000-862FFF (base 16) TripleOre
+ Kazernestraat 19
+ Venlo 5928 NL
+ NL
+
+70-B3-D5 (hex) AooGee Controls Co., LTD.
+1CC000-1CCFFF (base 16) AooGee Controls Co., LTD.
+ Siming District office building 14, Fu Lian
+ Xiamen Fujian 361000
+ CN
+
+70-B3-D5 (hex) TASK SISTEMAS DE COMPUTACAO LTDA
+961000-961FFF (base 16) TASK SISTEMAS DE COMPUTACAO LTDA
+ Rua 2 / 112 Jardim Itatiaia
+ Itatiaia Rio de Janeiro 27580-000
+ BR
+
+70-B3-D5 (hex) KST technology
+8A5000-8A5FFF (base 16) KST technology
+ KST B/D 4-5, Wiryeseong-daero 12-gil
+ Songpa-gu Seoul 05636
+ KR
+
+70-B3-D5 (hex) Advanced Ventilation Applications, Inc.
+DEA000-DEAFFF (base 16) Advanced Ventilation Applications, Inc.
+ 2158 Gordon Ave.
+ Menlo Park CA 94025
+ US
+
+70-B3-D5 (hex) Redfish Group Pty Ltd
+DA6000-DA6FFF (base 16) Redfish Group Pty Ltd
+ Level 3, 24 Little Edward Street
+ Spring Hill QLD 4000
+ AU
+
+70-B3-D5 (hex) shanghai qiaoqi zhinengkeji
+ED0000-ED0FFF (base 16) shanghai qiaoqi zhinengkeji
+ building 34, lane 333, laifang road
+ shanghai 201615
+ CN
+
+70-B3-D5 (hex) FUKUDA SANGYO CO., LTD.
+C9E000-C9EFFF (base 16) FUKUDA SANGYO CO., LTD.
+ Nazukari 996
+ Nagareyama Chiba 2700145
+ JP
+
+70-B3-D5 (hex) 3D Printing Specialists
+CDF000-CDFFFF (base 16) 3D Printing Specialists
+ 7916 Grow Ln
+ Houston TX 77040
+ US
+
+70-B3-D5 (hex) SL Audio A/S
+E43000-E43FFF (base 16) SL Audio A/S
+ Ulvevej 28, Danmark
+ Skive Denmark 7800
+ DK
+
+70-B3-D5 (hex) Hanwell Technology Co., Ltd.
+32D000-32DFFF (base 16) Hanwell Technology Co., Ltd.
+ 3F., No. 41, Dongxing Rd., Xinyi District.
+ Taipei 11070
+ TW
+
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
+E86000-E86FFF (base 16) YUYAMA MFG Co.,Ltd
+ 3-3-1
+ TOYONAKASHI OSAKA 561-0841
+ JP
+
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
+5C8000-5C8FFF (base 16) YUYAMA MFG Co.,Ltd
+ 3-3-1
+ TOYONAKASHI OSAKA 561-0841
+ JP
+
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
+742000-742FFF (base 16) YUYAMA MFG Co.,Ltd
+ 3-3-1
+ TOYONAKASHI OSAKA 561-0841
+ JP
+
+70-B3-D5 (hex) MyoungSung System
+9B4000-9B4FFF (base 16) MyoungSung System
+ 205, Manhae-ro, Danwon-gu
+ Ansan Gyeonggi-do 15421
+ KR
+
+70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG
+26C000-26CFFF (base 16) EA Elektroautomatik GmbH & Co. KG
+ Helmholtzstraße 31-33
+ Viersen NRW 41747
+ DE
+
+70-B3-D5 (hex) Groupe Paris-Turf
+9AB000-9ABFFF (base 16) Groupe Paris-Turf
+ 45 avenue Victor-Hugo, Bâtiment 270, 2e étage
+ AUBERVILLIERS 93300
+ FR
+
+70-B3-D5 (hex) Cygnetic Technologies (Pty) Ltd
+B94000-B94FFF (base 16) Cygnetic Technologies (Pty) Ltd
+ 10 Church Street
+ Cape Town 7550
+ ZA
+
+70-B3-D5 (hex) NINGBO CRRC TIMES TRANSDUCER TECHNOLOGY CO., LTD
+907000-907FFF (base 16) NINGBO CRRC TIMES TRANSDUCER TECHNOLOGY CO., LTD
+ No.138 Zhenyong Road
+ Ningbo Zhejiang 315021
+ CN
+
+70-B3-D5 (hex) WINNERS DIGITAL CORPORATION
+8A2000-8A2FFF (base 16) WINNERS DIGITAL CORPORATION
+ 3F, No. 4, Ln. 263, Chongyang Rd., Nangang Dist.,
+ Taipei City Taiwan 115-73
+ TW
+
+70-B3-D5 (hex) BEIJING ZGH SECURITY RESEARCH INSTITUTE CO., LTD
+6C3000-6C3FFF (base 16) BEIJING ZGH SECURITY RESEARCH INSTITUTE CO., LTD
+ Room 1407, Tianchen Plaza, Chaoyang District
+ BeiJing BeiJing 100020
+ CN
+
+70-B3-D5 (hex) SYS TEC electronic GmbH
+C64000-C64FFF (base 16) SYS TEC electronic GmbH
+ Am Windrad 2
+ Heinsdorfergrund D-08468
+ DE
+
+70-B3-D5 (hex) SilTerra Malaysia Sdn. Bhd.
+31B000-31BFFF (base 16) SilTerra Malaysia Sdn. Bhd.
+ Lot 8, Phase II, Kulim Hi-Tech Park
+ KULIM KEDAH 09000
+ MY
+
+70-B3-D5 (hex) DOLBY LABORATORIES, INC.
+3F5000-3F5FFF (base 16) DOLBY LABORATORIES, INC.
+ 100 Potrero Avenue
+ San Francisco CA 94103-4938
+ US
+
70-B3-D5 (hex) Flintab AB
D60000-D60FFF (base 16) Flintab AB
Kabelvägen 4
@@ -4271,12 +4439,6 @@ D9E000-D9EFFF (base 16) Grupo Epelsa S.L.
Alcala de Henares Madrid 28805
ES
-70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
-DB4000-DB4FFF (base 16) YUYAMA MFG Co.,Ltd
- 3-3-1
- TOYONAKASHI OSAKA 561-0841
- JP
-
70-B3-D5 (hex) Project Service S.a.s.
781000-781FFF (base 16) Project Service S.a.s.
Via Paderno 31/C
@@ -5801,9 +5963,6 @@ E59000-E59FFF (base 16) Fracarro srl
Amsterdam Noord-Holland 1017AW
NL
-70-B3-D5 (hex) Private
-73A000-73AFFF (base 16) Private
-
70-B3-D5 (hex) System 11 Sp. z o.o.
9DE000-9DEFFF (base 16) System 11 Sp. z o.o.
Wieniawskiego 18
@@ -5924,12 +6083,6 @@ D20000-D20FFF (base 16) Rheonics GmbH
Herford 32052
DE
-70-B3-D5 (hex) TELEPLATFORMS
-5FB000-5FBFFF (base 16) TELEPLATFORMS
- 2-ya Roshchinskaya street, 4,office I-8
- Moscow 115191
- RU
-
70-B3-D5 (hex) Kazan Networks Corporation
768000-768FFF (base 16) Kazan Networks Corporation
660 Auburn Folsom Rd, Suite 204
@@ -6149,6 +6302,228 @@ E9E000-E9EFFF (base 16) MSB Elektronik und Gerätebau GmbH
Crailsheim 74564
DE
+70-B3-D5 (hex) GL TECH CO.,LTD
+248000-248FFF (base 16) GL TECH CO.,LTD
+ No. Ten Changchun Road
+ ZHENGZHOU HENAN 455000
+ CN
+
+70-B3-D5 (hex) CAPSYS
+A0A000-A0AFFF (base 16) CAPSYS
+ ZI Parc technologique des Fontaines
+ BERNIN 38190
+ FR
+
+70-B3-D5 (hex) Centero
+CE2000-CE2FFF (base 16) Centero
+ 1640 Powers Ferry Road Bldg.14-360
+ Marietta GA 30067
+ US
+
+70-B3-D5 (hex) Ellenex Pty Ltd
+CD0000-CD0FFF (base 16) Ellenex Pty Ltd
+ 91 Tope Street
+ South Melbourne VIC 3205
+ AU
+
+70-B3-D5 (hex) Tecsys do Brasil Industrial Ltda
+9AA000-9AAFFF (base 16) Tecsys do Brasil Industrial Ltda
+ Rua Oros, 146
+ Sao Jose dos Campos SP 12237150
+ BR
+
+70-B3-D5 (hex) LINEAGE POWER PVT LTD.,
+0C9000-0C9FFF (base 16) LINEAGE POWER PVT LTD.,
+ 30-A1, KIADB, 1ST PHASE INDUSTRIAL ESTATE,KUMBALGODU, BANGALORE-MYSORE ROAD
+ BANGALORE KARNATAKA 560074
+ IN
+
+70-B3-D5 (hex) Heng Dian Technology Co., Ltd
+FEA000-FEAFFF (base 16) Heng Dian Technology Co., Ltd
+ No.9, Yunmei Road,Tianmulake Town
+ Liyang Jiangsu 213300
+ CN
+
+70-B3-D5 (hex) TELEPLATFORMS
+5FB000-5FBFFF (base 16) TELEPLATFORMS
+ Polbina st., 3/1
+ Moscow 109388
+ RU
+
+70-B3-D5 (hex) Private
+401000-401FFF (base 16) Private
+
+70-B3-D5 (hex) LG Electronics
+9E3000-9E3FFF (base 16) LG Electronics
+ 10, Magokjungang 10-ro, Gangseo-gu
+ Seoul 07796
+ KR
+
+70-B3-D5 (hex) HORIZON TELECOM
+960000-960FFF (base 16) HORIZON TELECOM
+ 6 rue de GUEUGNON
+ MONTCEAU LES MINES 71300
+ FR
+
+70-B3-D5 (hex) Beijing Daswell Science and Technology Co.LTD
+06F000-06FFFF (base 16) Beijing Daswell Science and Technology Co.LTD
+ 6th floor,Building B,Dachen Industry Park, NO.10 Jingyuan Street, BDA
+ Beijing Beijing 100176
+ CN
+
+70-B3-D5 (hex) Private
+73A000-73AFFF (base 16) Private
+
+70-B3-D5 (hex) Alere Technologies AS
+F52000-F52FFF (base 16) Alere Technologies AS
+ Kjelsaasveien 161
+ Oslo Oslo 0382
+ NO
+
+70-B3-D5 (hex) Impolux GmbH
+EEC000-EECFFF (base 16) Impolux GmbH
+ Boschstr. 7
+ Kastellaun RLP 56288
+ DE
+
+70-B3-D5 (hex) Beijing Nacao Technology Co., Ltd.
+105000-105FFF (base 16) Beijing Nacao Technology Co., Ltd.
+ 1912B, Zhongguancunkemao Building, Zhongguancun Da Jie
+ Beijing 100080
+ CN
+
+70-B3-D5 (hex) machineQ
+3E6000-3E6FFF (base 16) machineQ
+ 1900 market st
+ philadelphia PA 19103
+ US
+
+70-B3-D5 (hex) eumig industrie-TV GmbH.
+AA2000-AA2FFF (base 16) eumig industrie-TV GmbH.
+ Gewerbeparkstrasse 9
+ Anif Salzburg 5081
+ AT
+
+70-B3-D5 (hex) FSTUDIO CO LTD
+C0B000-C0BFFF (base 16) FSTUDIO CO LTD
+ Yanagawa Bldg. 2F 5-16-13
+ Watanabe-Dori Chuo-ku Fukuoka Fukuoka 810-0004
+ JP
+
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
+DB4000-DB4FFF (base 16) YUYAMA MFG Co.,Ltd
+ 3-3-1
+ TOYONAKASHI OSAKA 561-0841
+ JP
+
+70-B3-D5 (hex) Smith Meter, Inc.
+706000-706FFF (base 16) Smith Meter, Inc.
+ 1602 Wagner Ave.
+ Erie 16514
+ US
+
+70-B3-D5 (hex) EGICON SRL
+6F7000-6F7FFF (base 16) EGICON SRL
+ Via Posta Vecchia 36
+ Mirandola Modena 41037
+ IT
+
+70-B3-D5 (hex) Symetrics Industries d.b.a. Extant Aerospace
+0A8000-0A8FFF (base 16) Symetrics Industries d.b.a. Extant Aerospace
+ 1615 West NASA Blvd
+ Melbourne FL 32901
+ US
+
+70-B3-D5 (hex) CRESPRIT INC.
+C38000-C38FFF (base 16) CRESPRIT INC.
+ D-315 ,177, Jeongjail-ro, Bundang-gu
+ Seongnam-si 13557
+ KR
+
+70-B3-D5 (hex) alfamation spa
+675000-675FFF (base 16) alfamation spa
+ via cadore 21
+ lissone mb 20851
+ IT
+
+70-B3-D5 (hex) KST technology
+C05000-C05FFF (base 16) KST technology
+ KST B/D 4-5, Wiryeseong-daero 12-gil
+ Songpa-gu Seoul 05636
+ KR
+
+70-B3-D5 (hex) ETA Technology Pvt Ltd
+A94000-A94FFF (base 16) ETA Technology Pvt Ltd
+ No. 484-D, 13th Cross, IV Phase, Peenya Industrial Area,
+ Bangalore Karnataka 560058
+ IN
+
+70-B3-D5 (hex) Newshine
+A64000-A64FFF (base 16) Newshine
+ Pingcheng Rd
+ Shanghai Shanghai 201800
+ CN
+
+70-B3-D5 (hex) Guan Show Technologe Co., Ltd.
+E2B000-E2BFFF (base 16) Guan Show Technologe Co., Ltd.
+ No.127, Jianguo 1st Rd., Lingya Dist.
+ Kaohsiung City 802
+ TW
+
+70-B3-D5 (hex) CMT Medical technologies
+950000-950FFF (base 16) CMT Medical technologies
+ Hacarmel 7/2
+ Yoqneam 20692
+ IL
+
+70-B3-D5 (hex) Harvard Technology Ltd
+56A000-56AFFF (base 16) Harvard Technology Ltd
+ Tyler Close, Normanton
+ Wakefield WF6 1RL
+ GB
+
+70-B3-D5 (hex) Keepen
+69C000-69CFFF (base 16) Keepen
+ 12, rue Anselme
+ Saint-Ouen 93400
+ FR
+
+70-B3-D5 (hex) Abionic
+BC1000-BC1FFF (base 16) Abionic
+ Route de la Corniche 5
+ Epalinges 1066
+ CH
+
+70-B3-D5 (hex) MiWave Consulting, LLC
+0E1000-0E1FFF (base 16) MiWave Consulting, LLC
+ 1117 Paine Court
+ Raleigh NC 27609
+ US
+
+70-B3-D5 (hex) PROEL TSI s.r.l.
+5CF000-5CFFFF (base 16) PROEL TSI s.r.l.
+ VIA DIVISIONE JULIA, 10
+ MANZANO UD 33044
+ IT
+
+70-B3-D5 (hex) Compusign Systems Pty Ltd
+050000-050FFF (base 16) Compusign Systems Pty Ltd
+ 8/10 Clarice Road
+ Box Hill Victoria 3128
+ AU
+
+70-B3-D5 (hex) Advansid
+3F7000-3F7FFF (base 16) Advansid
+ Via Alla Cascata 56/C
+ Trento 38123
+ IT
+
+70-B3-D5 (hex) SCHMID electronic
+764000-764FFF (base 16) SCHMID electronic
+ Badstrasse 39
+ Reutlingen 72766
+ DE
+
70-B3-D5 (hex) Schildknecht AG
494000-494FFF (base 16) Schildknecht AG
Haugweg 26
@@ -6758,12 +7133,6 @@ D46000-D46FFF (base 16) Contineo s.r.o.
Ermatingen Thurgau 8272
CH
-70-B3-D5 (hex) MB Connect Line GmbH
-2CF000-2CFFFF (base 16) MB Connect Line GmbH
- Winnettener Straße 6
- Dinkelsbühl Bavaria 91550
- DE
-
70-B3-D5 (hex) LECIP CORPORATION
A50000-A50FFF (base 16) LECIP CORPORATION
1260-1
@@ -8006,9 +8375,6 @@ CCF000-CCFFFF (base 16) Netberg
Ajax Ontario L1s7H4
CA
-70-B3-D5 (hex) Private
-376000-376FFF (base 16) Private
-
70-B3-D5 (hex) Centuryarks Ltd.,
52C000-52CFFF (base 16) Centuryarks Ltd.,
3-13-1,Nishiazabu
@@ -8261,12 +8627,6 @@ A8B000-A8BFFF (base 16) Giant Power Technology Biomedical Corporation
YIZHUANG economic development zone, District Daxing Beijing 100176
CN
-70-B3-D5 (hex) Honeywell
-F70000-F70FFF (base 16) Honeywell
- 13350 US Highway 19 N
- Clearwater 33764
- US
-
70-B3-D5 (hex) Terragene S.A
9CE000-9CEFFF (base 16) Terragene S.A
Guemes 2879
@@ -8297,12 +8657,6 @@ FFC000-FFCFFF (base 16) Symetrics Industries d.b.a. Extant Aerospace
Melbourne FL 32901
US
-70-B3-D5 (hex) Private
-30E000-30EFFF (base 16) Private
-
-70-B3-D5 (hex) Private
-4F8000-4F8FFF (base 16) Private
-
70-B3-D5 (hex) Hexagon Metrology SAS
5E0000-5E0FFF (base 16) Hexagon Metrology SAS
2 rue François Arago
@@ -8339,12 +8693,6 @@ FFC000-FFCFFF (base 16) Symetrics Industries d.b.a. Extant Aerospace
SEOUL 04790
KR
-70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
-B6A000-B6AFFF (base 16) YUYAMA MFG Co.,Ltd
- 3-3-1
- TOYONAKASHI OSAKA 561-0841
- JP
-
70-B3-D5 (hex) Chelsea Technologies Group Ltd
579000-579FFF (base 16) Chelsea Technologies Group Ltd
55, Central Avenue
@@ -8621,6 +8969,258 @@ C42000-C42FFF (base 16) CRDE
Fontaneto d'Agogna Novara 28010
IT
+70-B3-D5 (hex) Shenzhen INVT Electric Co.,Ltd
+1D0000-1D0FFF (base 16) Shenzhen INVT Electric Co.,Ltd
+ INVT Bldg., GaoFa Scientific Park, Longjing, Nanshan, Shenzhen.
+ Shenzhen Guangdong 518055
+ CN
+
+70-B3-D5 (hex) Vtron Pty Ltd
+400000-400FFF (base 16) Vtron Pty Ltd
+ Unit 2, 62 Township Drive West
+ West Burleigh Queensland 4219
+ AU
+
+70-B3-D5 (hex) Vtron Pty Ltd
+B2B000-B2BFFF (base 16) Vtron Pty Ltd
+ Unit 2, 62 Township Drive West
+ West Burleigh Queensland 4219
+ AU
+
+70-B3-D5 (hex) Vtron Pty Ltd
+E0F000-E0FFFF (base 16) Vtron Pty Ltd
+ Unit 2, 62 Township Drive West
+ West Burleigh Queensland 4219
+ AU
+
+70-B3-D5 (hex) KRONOTECH SRL
+8C8000-8C8FFF (base 16) KRONOTECH SRL
+ VIALE UNGHERIA 125
+ UDINE ITALY/UDINE 33100
+ IT
+
+70-B3-D5 (hex) Particle sizing systems
+670000-670FFF (base 16) Particle sizing systems
+ 8203 Kristel Cir
+ New Port Richey FL 34652
+ US
+
+70-B3-D5 (hex) Grupo Epelsa S.L.
+4E1000-4E1FFF (base 16) Grupo Epelsa S.L.
+ C/ Punto Net,3
+ Alcala de Henares Madrid 28805
+ ES
+
+70-B3-D5 (hex) Waterkotte GmbH
+7EA000-7EAFFF (base 16) Waterkotte GmbH
+ Gewerkenstr. 15
+ Herne 44628
+ DE
+
+70-B3-D5 (hex) Imecon Engineering SrL
+5E3000-5E3FFF (base 16) Imecon Engineering SrL
+ via Gerola 13/15
+ Fiesco CR 26010
+ IT
+
+70-B3-D5 (hex) ELBIT SYSTEMS BMD AND LAND EW - ELISRA LTD
+24F000-24FFFF (base 16) ELBIT SYSTEMS BMD AND LAND EW - ELISRA LTD
+ Hamerchava 29
+ holon 58101
+ IL
+
+70-B3-D5 (hex) HiDes, Inc.
+837000-837FFF (base 16) HiDes, Inc.
+ 6F, No.86, Baozhong Rd., Xindian Dist.,
+ New Taipei City New Taipei City 23144
+ TW
+
+70-B3-D5 (hex) OptoPrecision GmbH
+4F9000-4F9FFF (base 16) OptoPrecision GmbH
+ Auf der Höhe 15
+ Bremen Bremen 28357
+ DE
+
+70-B3-D5 (hex) OSUNG LST CO.,LTD.
+B64000-B64FFF (base 16) OSUNG LST CO.,LTD.
+ #433-31, Sandong-ro, Eumbong-myeon
+ Asan-si Chungcheongnam-do 31418
+ KR
+
+70-B3-D5 (hex) Impulse Automation
+7A3000-7A3FFF (base 16) Impulse Automation
+ Obuhovskoy Oborony 120-B
+ Saint Petersburg Saint Petersburg 192012
+ RU
+
+70-B3-D5 (hex) SENSO2ME
+631000-631FFF (base 16) SENSO2ME
+ Zandhoef 16
+ KASTERLEE België 2460
+ BE
+
+70-B3-D5 (hex) Infodev Electronic Designers Intl.
+DBF000-DBFFFF (base 16) Infodev Electronic Designers Intl.
+ 1995 rue Frank-Carrel Suite 202
+ Quebec Quebec G1N4H9
+ CA
+
+70-B3-D5 (hex) SENSO2ME
+F7A000-F7AFFF (base 16) SENSO2ME
+ Zandhoef 16
+ KASTERLEE België 2460
+ BE
+
+70-B3-D5 (hex) KOSMEK.Ltd
+BB9000-BB9FFF (base 16) KOSMEK.Ltd
+ Murodani 2-1-5, Nishi-ku
+ Kobe-City Hyogo Pref. 6512241
+ JP
+
+70-B3-D5 (hex) Quantum Opus, LLC
+602000-602FFF (base 16) Quantum Opus, LLC
+ 45211 Helm St
+ Plymouth MI 48170
+ US
+
+70-B3-D5 (hex) Shanghai YuanAn Environmental Protection Technology Co.,Ltd
+6D8000-6D8FFF (base 16) Shanghai YuanAn Environmental Protection Technology Co.,Ltd
+ Rm213/225,Oriental Pearl European City,No 285 East luochuan Road
+ Shanghai Shanghai 200072
+ CN
+
+70-B3-D5 (hex) ST Aerospace Systems
+27F000-27FFFF (base 16) ST Aerospace Systems
+ 505A Airport Road Paya Lebar
+ Singapore Singapore 539934
+ SG
+
+70-B3-D5 (hex) Sierra Nevada Corporation
+339000-339FFF (base 16) Sierra Nevada Corporation
+ 444 Salomon Circle
+ Sparks NV 89434
+ US
+
+70-B3-D5 (hex) Hi Tech Systems Ltd
+4B4000-4B4FFF (base 16) Hi Tech Systems Ltd
+ Holbrook House, Oakley Lane
+ Basingstoke Hampshire RG23 7JY
+ GB
+
+70-B3-D5 (hex) Hermann Lümmen GmbH
+D4B000-D4BFFF (base 16) Hermann Lümmen GmbH
+ Biberweg 32
+ Troisdorf 53842
+ DE
+
+70-B3-D5 (hex) DEUTA-WERKE GmbH
+EF5000-EF5FFF (base 16) DEUTA-WERKE GmbH
+ Paffrather Str. 140
+ Bergisch Gladbach North Rhine-Westphalia 51465
+ DE
+
+70-B3-D5 (hex) BigStuff3, Inc.
+64E000-64EFFF (base 16) BigStuff3, Inc.
+ 4352 Fenton Rd
+ Hartland MI 48353
+ US
+
+70-B3-D5 (hex) Teko Telecom Srl
+29C000-29CFFF (base 16) Teko Telecom Srl
+ via Meucci 24/a
+ Castel San Pietro Terme Bologna 40024
+ IT
+
+70-B3-D5 (hex) Henrich Electronics Corporation
+436000-436FFF (base 16) Henrich Electronics Corporation
+ 225 Deming Place
+ Westmont IL 60559
+ US
+
+70-B3-D5 (hex) Cubitech
+7D0000-7D0FFF (base 16) Cubitech
+ Likourgou 9
+ Athens 17676
+ GR
+
+70-B3-D5 (hex) Euklis by GSG International
+AD8000-AD8FFF (base 16) Euklis by GSG International
+ via Colombo 23
+ Trezzano sul Naviglio MI 20090
+ IT
+
+70-B3-D5 (hex) Chengdu Cove Technology CO.,LTD
+24E000-24EFFF (base 16) Chengdu Cove Technology CO.,LTD
+ 6-419, Hi-tech Incubation Park, No.1480 Tianfu Ave
+ Chengdu Sichuan 610000
+ CN
+
+70-B3-D5 (hex) Star Systems International
+5EF000-5EFFFF (base 16) Star Systems International
+ Unit 04, 12/F Vanta Industrial Centre, 21-33 Tai Lin Pai Road
+ Kwai Chung 852
+ HK
+
+70-B3-D5 (hex) ZAO ZEO
+B43000-B43FFF (base 16) ZAO ZEO
+ Khachaturiana 14a
+ Moscow 127562
+ RU
+
+70-B3-D5 (hex) Robotelf Technologies (Chengdu) Co., Ltd.
+1A6000-1A6FFF (base 16) Robotelf Technologies (Chengdu) Co., Ltd.
+ N3-4-1-1914, Global Center, No. 1700, Tianfu Road North, High-rech Zone
+ Chengdu City Sichuan 610041
+ CN
+
+70-B3-D5 (hex) LG Electronics
+257000-257FFF (base 16) LG Electronics
+ 10, Magokjungang 10-ro, Gangseo-gu
+ Seoul 07796
+ KR
+
+70-B3-D5 (hex) SLAT
+920000-920FFF (base 16) SLAT
+ 11 Rue Jean-Elysée DUPUY
+ Champagne au Mont d'Or Rhône 69543
+ FR
+
+70-B3-D5 (hex) Private
+FFF000-FFFFFF (base 16) Private
+
+70-B3-D5 (hex) Technica Engineering GmbH
+4C0000-4C0FFF (base 16) Technica Engineering GmbH
+ Leopoldstraße 236
+ Munich 80807
+ DE
+
+70-B3-D5 (hex) AIROBOT OÜ
+1D3000-1D3FFF (base 16) AIROBOT OÜ
+ Pardi 32-1
+ Pärnu 80016
+ EE
+
+70-B3-D5 (hex) Private
+6CF000-6CFFFF (base 16) Private
+
+70-B3-D5 (hex) Touchnet/OneCard
+478000-478FFF (base 16) Touchnet/OneCard
+ 2115 Chapman Rd. Suite 159
+ Chattanooga TN 37421
+ US
+
+70-B3-D5 (hex) Convergent Design
+1F8000-1F8FFF (base 16) Convergent Design
+ 4525 Northpark Drive
+ Colorado Springs CO 80918
+ US
+
+70-B3-D5 (hex) Private
+4F8000-4F8FFF (base 16) Private
+
+70-B3-D5 (hex) Private
+376000-376FFF (base 16) Private
+
70-B3-D5 (hex) ENTEC Electric & Electronic Co., LTD.
92B000-92BFFF (base 16) ENTEC Electric & Electronic Co., LTD.
78-2 Buncheon-ri, Bongdam-eup
@@ -8912,11 +9512,11 @@ D62000-D62FFF (base 16) Andasis Elektronik San. ve Tic. A.Ş.
Gap France 05000
FR
-70-B3-D5 (hex) Touchnet/OneCard
-478000-478FFF (base 16) Touchnet/OneCard
- 2115 Chapman Rd. Suite 159
- Chattanooga TN 37421
- US
+70-B3-D5 (hex) SHANGHAI IRISIAN OPTRONICS TECHNOLOGY CO.,LTD.
+2D2000-2D2FFF (base 16) SHANGHAI IRISIAN OPTRONICS TECHNOLOGY CO.,LTD.
+ 8F, NO.800, Huanhu NO.2 Road (W), Pudong New District, Shanghai 201306, China
+ Shanghai Shanghai 201306
+ CN
70-B3-D5 (hex) Human Systems Integration
085000-085FFF (base 16) Human Systems Integration
@@ -8924,248 +9524,164 @@ D62000-D62FFF (base 16) Andasis Elektronik San. ve Tic. A.Ş.
Walpole MA 02170
US
-70-B3-D5 (hex) Shenzhen INVT Electric Co.,Ltd
-1D0000-1D0FFF (base 16) Shenzhen INVT Electric Co.,Ltd
- INVT Bldg., GaoFa Scientific Park, Longjing, Nanshan, Shenzhen.
- Shenzhen Guangdong 518055
+70-B3-D5 (hex) Guilin Tryin Technology Co.,Ltd
+460000-460FFF (base 16) Guilin Tryin Technology Co.,Ltd
+ Room C-306, Innovation Building,Information Industry Park, Chaoyang Road,Guilin,China
+ GuiLin Guangxi 541000
CN
-70-B3-D5 (hex) Vtron Pty Ltd
-400000-400FFF (base 16) Vtron Pty Ltd
- Unit 2, 62 Township Drive West
- West Burleigh Queensland 4219
- AU
-
-70-B3-D5 (hex) Vtron Pty Ltd
-B2B000-B2BFFF (base 16) Vtron Pty Ltd
- Unit 2, 62 Township Drive West
- West Burleigh Queensland 4219
- AU
-
-70-B3-D5 (hex) Vtron Pty Ltd
-E0F000-E0FFFF (base 16) Vtron Pty Ltd
- Unit 2, 62 Township Drive West
- West Burleigh Queensland 4219
- AU
-
-70-B3-D5 (hex) KRONOTECH SRL
-8C8000-8C8FFF (base 16) KRONOTECH SRL
- VIALE UNGHERIA 125
- UDINE ITALY/UDINE 33100
- IT
+70-B3-D5 (hex) Invisible Systems Limited
+5F2000-5F2FFF (base 16) Invisible Systems Limited
+ 9 Beetham Road
+ Milnthorpe Cumbria LA7 7QL
+ GB
-70-B3-D5 (hex) Particle sizing systems
-670000-670FFF (base 16) Particle sizing systems
- 8203 Kristel Cir
- New Port Richey FL 34652
+70-B3-D5 (hex) Blue Access Inc
+C66000-C66FFF (base 16) Blue Access Inc
+ P.O. Box
+ Erie CO 80516
US
-70-B3-D5 (hex) Grupo Epelsa S.L.
-4E1000-4E1FFF (base 16) Grupo Epelsa S.L.
- C/ Punto Net,3
- Alcala de Henares Madrid 28805
- ES
-
-70-B3-D5 (hex) Waterkotte GmbH
-7EA000-7EAFFF (base 16) Waterkotte GmbH
- Gewerkenstr. 15
- Herne 44628
- DE
+70-B3-D5 (hex) INVIXIUM ACCESS INC.
+87D000-87DFFF (base 16) INVIXIUM ACCESS INC.
+ 50 ACADIA AVE, 310
+ MARKHAM Ontario L3R0B3
+ CA
-70-B3-D5 (hex) Imecon Engineering SrL
-5E3000-5E3FFF (base 16) Imecon Engineering SrL
- via Gerola 13/15
- Fiesco CR 26010
+70-B3-D5 (hex) TEX COMPUTER SRL
+5FA000-5FAFFF (base 16) TEX COMPUTER SRL
+ VIA MERCADANTE 35
+ CATTOLICA RIMINI 47841
IT
-70-B3-D5 (hex) ELBIT SYSTEMS BMD AND LAND EW - ELISRA LTD
-24F000-24FFFF (base 16) ELBIT SYSTEMS BMD AND LAND EW - ELISRA LTD
- Hamerchava 29
- holon 58101
- IL
-
-70-B3-D5 (hex) HiDes, Inc.
-837000-837FFF (base 16) HiDes, Inc.
- 6F, No.86, Baozhong Rd., Xindian Dist.,
- New Taipei City New Taipei City 23144
- TW
+70-B3-D5 (hex) Private
+A9F000-A9FFFF (base 16) Private
-70-B3-D5 (hex) OptoPrecision GmbH
-4F9000-4F9FFF (base 16) OptoPrecision GmbH
- Auf der Höhe 15
- Bremen Bremen 28357
- DE
+70-B3-D5 (hex) Burk Technology
+985000-985FFF (base 16) Burk Technology
+ 7 Beaver Brook road
+ Littleton MA 01460
+ US
-70-B3-D5 (hex) OSUNG LST CO.,LTD.
-B64000-B64FFF (base 16) OSUNG LST CO.,LTD.
- #433-31, Sandong-ro, Eumbong-myeon
- Asan-si Chungcheongnam-do 31418
- KR
+70-B3-D5 (hex) Private
+30E000-30EFFF (base 16) Private
-70-B3-D5 (hex) Impulse Automation
-7A3000-7A3FFF (base 16) Impulse Automation
- Obuhovskoy Oborony 120-B
- Saint Petersburg Saint Petersburg 192012
- RU
+70-B3-D5 (hex) Moduware PTY LTD
+FC8000-FC8FFF (base 16) Moduware PTY LTD
+ 502/37 Swanston Street
+ Melbourne Victoria 3000
+ AU
-70-B3-D5 (hex) SENSO2ME
-631000-631FFF (base 16) SENSO2ME
- Zandhoef 16
- KASTERLEE België 2460
- BE
+70-B3-D5 (hex) wallbe GmbH
+07B000-07BFFF (base 16) wallbe GmbH
+ Paderborner Straße 76
+ Schlangen NRW 33189
+ DE
-70-B3-D5 (hex) Infodev Electronic Designers Intl.
-DBF000-DBFFFF (base 16) Infodev Electronic Designers Intl.
- 1995 rue Frank-Carrel Suite 202
- Quebec Quebec G1N4H9
- CA
+70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme
+2CF000-2CFFFF (base 16) MB connect line GmbH Fernwartungssysteme
+ Winnettener Straße 6
+ Dinkelsbühl Bavaria 91550
+ DE
-70-B3-D5 (hex) SENSO2ME
-F7A000-F7AFFF (base 16) SENSO2ME
- Zandhoef 16
- KASTERLEE België 2460
- BE
+70-B3-D5 (hex) Sensefarm AB
+546000-546FFF (base 16) Sensefarm AB
+ Mobilvagen 10
+ Lund 22362
+ SE
-70-B3-D5 (hex) KOSMEK.Ltd
-BB9000-BB9FFF (base 16) KOSMEK.Ltd
- Murodani 2-1-5, Nishi-ku
- Kobe-City Hyogo Pref. 6512241
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
+B6A000-B6AFFF (base 16) YUYAMA MFG Co.,Ltd
+ 3-3-1
+ TOYONAKASHI OSAKA 561-0841
JP
-70-B3-D5 (hex) Quantum Opus, LLC
-602000-602FFF (base 16) Quantum Opus, LLC
- 45211 Helm St
- Plymouth MI 48170
- US
-
-70-B3-D5 (hex) Shanghai YuanAn Environmental Protection Technology Co.,Ltd
-6D8000-6D8FFF (base 16) Shanghai YuanAn Environmental Protection Technology Co.,Ltd
- Rm213/225,Oriental Pearl European City,No 285 East luochuan Road
- Shanghai Shanghai 200072
- CN
-
-70-B3-D5 (hex) ST Aerospace Systems
-27F000-27FFFF (base 16) ST Aerospace Systems
- 505A Airport Road Paya Lebar
- Singapore Singapore 539934
- SG
+70-B3-D5 (hex) Coheros Oy
+D2E000-D2EFFF (base 16) Coheros Oy
+ Korkeakoulunkatu 1
+ Tampere 33720
+ FI
-70-B3-D5 (hex) Sierra Nevada Corporation
-339000-339FFF (base 16) Sierra Nevada Corporation
- 444 Salomon Circle
- Sparks NV 89434
+70-B3-D5 (hex) Lexi Devices, Inc.
+AC4000-AC4FFF (base 16) Lexi Devices, Inc.
+ 2342 Shattuck Ave, #260
+ Berkeley 94704
US
-70-B3-D5 (hex) Hi Tech Systems Ltd
-4B4000-4B4FFF (base 16) Hi Tech Systems Ltd
- Holbrook House, Oakley Lane
- Basingstoke Hampshire RG23 7JY
- GB
-
-70-B3-D5 (hex) Hermann Lümmen GmbH
-D4B000-D4BFFF (base 16) Hermann Lümmen GmbH
- Biberweg 32
- Troisdorf 53842
- DE
-
-70-B3-D5 (hex) DEUTA-WERKE GmbH
-EF5000-EF5FFF (base 16) DEUTA-WERKE GmbH
- Paffrather Str. 140
- Bergisch Gladbach North Rhine-Westphalia 51465
- DE
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
+85F000-85FFFF (base 16) YUYAMA MFG Co.,Ltd
+ 3-3-1
+ TOYONAKASHI OSAKA 561-0841
+ JP
-70-B3-D5 (hex) BigStuff3, Inc.
-64E000-64EFFF (base 16) BigStuff3, Inc.
- 4352 Fenton Rd
- Hartland MI 48353
+70-B3-D5 (hex) Millennial Net, Inc.
+3B0000-3B0FFF (base 16) Millennial Net, Inc.
+ 24 Hartwell Avenue
+ Lexington MA 02421
US
-70-B3-D5 (hex) Teko Telecom Srl
-29C000-29CFFF (base 16) Teko Telecom Srl
- via Meucci 24/a
- Castel San Pietro Terme Bologna 40024
- IT
+70-B3-D5 (hex) ETA-USA
+23F000-23FFFF (base 16) ETA-USA
+ 16170 Vineyard Blvd., #180
+ Morgan Hill CA 95037
+ US
-70-B3-D5 (hex) Henrich Electronics Corporation
-436000-436FFF (base 16) Henrich Electronics Corporation
- 225 Deming Place
- Westmont IL 60559
+70-B3-D5 (hex) Honeywell
+F70000-F70FFF (base 16) Honeywell
+ 13350 US Highway 19 N
+ Clearwater 33764
US
-70-B3-D5 (hex) Cubitech
-7D0000-7D0FFF (base 16) Cubitech
- Likourgou 9
- Athens 17676
- GR
+70-B3-D5 (hex) VISION SYSTEMS AURTOMOTIVE (SAFETY TECH)
+948000-948FFF (base 16) VISION SYSTEMS AURTOMOTIVE (SAFETY TECH)
+ CHEMIN DE CHIRADIE
+ BRIGNAIS RHONE ALPES AUVERGNE 69530
+ FR
-70-B3-D5 (hex) Euklis by GSG International
-AD8000-AD8FFF (base 16) Euklis by GSG International
- via Colombo 23
- Trezzano sul Naviglio MI 20090
+70-B3-D5 (hex) IDEA SPA
+415000-415FFF (base 16) IDEA SPA
+ VIA PARALLELA 2/4
+ VILLA BARTOLOMEA VERONA 37049
IT
-70-B3-D5 (hex) Chengdu Cove Technology CO.,LTD
-24E000-24EFFF (base 16) Chengdu Cove Technology CO.,LTD
- 6-419, Hi-tech Incubation Park, No.1480 Tianfu Ave
- Chengdu Sichuan 610000
- CN
-
-70-B3-D5 (hex) Star Systems International
-5EF000-5EFFFF (base 16) Star Systems International
- Unit 04, 12/F Vanta Industrial Centre, 21-33 Tai Lin Pai Road
- Kwai Chung 852
- HK
-
-70-B3-D5 (hex) ZAO ZEO
-B43000-B43FFF (base 16) ZAO ZEO
- Khachaturiana 14a
- Moscow 127562
- RU
-
-70-B3-D5 (hex) Robotelf Technologies (Chengdu) Co., Ltd.
-1A6000-1A6FFF (base 16) Robotelf Technologies (Chengdu) Co., Ltd.
- N3-4-1-1914, Global Center, No. 1700, Tianfu Road North, High-rech Zone
- Chengdu City Sichuan 610041
- CN
-
-70-B3-D5 (hex) LG Electronics
-257000-257FFF (base 16) LG Electronics
- 10, Magokjungang 10-ro, Gangseo-gu
- Seoul 07796
- KR
-
-70-B3-D5 (hex) SLAT
-920000-920FFF (base 16) SLAT
- 11 Rue Jean-Elysée DUPUY
- Champagne au Mont d'Or Rhône 69543
- FR
+70-B3-D5 (hex) Robotic Research, LLC
+EB4000-EB4FFF (base 16) Robotic Research, LLC
+ 555 Quince Orchard Rd, Suite 300
+ Gaithersburg MD 20878
+ US
-70-B3-D5 (hex) Private
-A9F000-A9FFFF (base 16) Private
+70-B3-D5 (hex) SYSCO Sicherheitssysteme GmbH
+471000-471FFF (base 16) SYSCO Sicherheitssysteme GmbH
+ Nebenstrasse 13
+ Hasselroth Hessen 63594
+ DE
70-B3-D5 (hex) Private
-FFF000-FFFFFF (base 16) Private
+66A000-66AFFF (base 16) Private
-70-B3-D5 (hex) Technica Engineering GmbH
-4C0000-4C0FFF (base 16) Technica Engineering GmbH
- Leopoldstraße 236
- Munich 80807
- DE
+70-B3-D5 (hex) U-JIN Mesco Co., Ltd.
+868000-868FFF (base 16) U-JIN Mesco Co., Ltd.
+ Nakajima-cho 18-22
+ Nishinomiya Hyogo 663-8105
+ JP
-70-B3-D5 (hex) AIROBOT OÜ
-1D3000-1D3FFF (base 16) AIROBOT OÜ
- Pardi 32-1
- Pärnu 80016
- EE
+70-B3-D5 (hex) Koco Motion US LLC
+707000-707FFF (base 16) Koco Motion US LLC
+ 335 Cochrane Circle
+ Morgan Hill CA 95037
+ US
-70-B3-D5 (hex) Private
-6CF000-6CFFFF (base 16) Private
+70-B3-D5 (hex) Bespoon
+0F7000-0F7FFF (base 16) Bespoon
+ 17 rue du Lac St andre
+ Le bourget du Lac 73370
+ FR
-70-B3-D5 (hex) SHANGHAI IRISIAN OPTRONICS TECHNOLOGY CO.,LTD.
-2D2000-2D2FFF (base 16) SHANGHAI IRISIAN OPTRONICS TECHNOLOGY CO.,LTD.
- 8F, NO.800, Huanhu NO.2 Road (W), Pudong New District, Shanghai 201306, China
- Shanghai Shanghai 201306
- CN
+70-B3-D5 (hex) Elektronik Art S.C.
+82D000-82DFFF (base 16) Elektronik Art S.C.
+ Mełgiewska 80
+ Lublin 20-234
+ PL
70-B3-D5 (hex) Innitive B.V.
66B000-66BFFF (base 16) Innitive B.V.
@@ -9419,12 +9935,6 @@ EA4000-EA4FFF (base 16) Grupo Epelsa S.L.
Passfield, Liphook Hampshire GU30 7SB
GB
-70-B3-D5 (hex) Honeywell International Inc.
-F4D000-F4DFFF (base 16) Honeywell International Inc.
- Aerospace - ETS
- Clearwater Florida 33764
- US
-
70-B3-D5 (hex) CT Company
230000-230FFF (base 16) CT Company
9F.-1, No,Jian 8th Rd.
@@ -9575,12 +10085,6 @@ C3C000-C3CFFF (base 16) PEEK TRAFFIC
HOUSTON TEXAS 77086
US
-70-B3-D5 (hex) MB Connect Line GmbH
-17F000-17FFFF (base 16) MB Connect Line GmbH
- Winnettener Straße 6
- Dinkelsbühl Bavaria 91550
- DE
-
70-B3-D5 (hex) PCME Ltd.
FE8000-FE8FFF (base 16) PCME Ltd.
Clearview Building
@@ -10307,12 +10811,6 @@ A92000-A92FFF (base 16) Grossenbacher Systeme AG
St. Gallen 9008
CH
-70-B3-D5 (hex) MB Connect Line GmbH
-B39000-B39FFF (base 16) MB Connect Line GmbH
- Winnettener Straße 5
- Dinkelsbühl Bavaria 91550
- DE
-
70-B3-D5 (hex) Hatel Elektronik LTD. STI.
1E3000-1E3FFF (base 16) Hatel Elektronik LTD. STI.
1348 Sok. No:2/V Keremogli Is Merkezi - Yenisehir
@@ -11063,12 +11561,6 @@ D9A000-D9AFFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd
Wuhan Hubei 430074
CN
-70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
-9C7000-9C7FFF (base 16) YUYAMA MFG Co.,Ltd
- 3-3-1
- TOYONAKASHI OSAKA 561-0841
- JP
-
70-B3-D5 (hex) Wuhan Xingtuxinke ELectronic Co.,Ltd
32A000-32AFFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd
NO.C3-8F,Software Park,Optics Valley,East Lake Development Zone,Wuhan,Hubei,China
@@ -12212,6 +12704,258 @@ DC8000-DC8FFF (base 16) Enertex Bayern GmbH
Hazelwood MO 63042
US
+70-B3-D5 (hex) CHRONOMEDIA
+21F000-21FFFF (base 16) CHRONOMEDIA
+ #508, 1130, Beoman-ro, Geumcheon-gu
+ Seoul 08595
+ KR
+
+70-B3-D5 (hex) TATTILE SRL
+EEF000-EEFFFF (base 16) TATTILE SRL
+ VIA DONIZETTI, 1/3/5
+ MAIRANO BRESCIA 25030
+ IT
+
+70-B3-D5 (hex) Acrodea, Inc.
+67D000-67DFFF (base 16) Acrodea, Inc.
+ 3F, Daisan Yamada Bldg., 22 Aizumi-cho
+ Shinjuku-ku Tokyo 1600005
+ JP
+
+70-B3-D5 (hex) provedo
+A54000-A54FFF (base 16) provedo
+ Friedrich-Ebert-Straße, 63
+ Leipzig 04109
+ DE
+
+70-B3-D5 (hex) STREGA
+770000-770FFF (base 16) STREGA
+ Dreve de la Meute 31
+ Waterloo 1410
+ BE
+
+70-B3-D5 (hex) RCH Italia SpA
+857000-857FFF (base 16) RCH Italia SpA
+ Via Cendon 39
+ SILEA Treviso 31057
+ IT
+
+70-B3-D5 (hex) IONETECH
+876000-876FFF (base 16) IONETECH
+ #50,sicheongseo4gil
+ yeosu jeonnam 59674
+ KR
+
+70-B3-D5 (hex) Procon Electronics Pty Ltd
+8EB000-8EBFFF (base 16) Procon Electronics Pty Ltd
+ P O Box 164
+ Seven Hills NSW 1730
+ AU
+
+70-B3-D5 (hex) Xylon
+C1A000-C1AFFF (base 16) Xylon
+ Fallerovo setaliste 22
+ Zagreb 10000
+ HR
+
+70-B3-D5 (hex) Rako Controls Ltd
+084000-084FFF (base 16) Rako Controls Ltd
+ Knight Road
+ Rochester Kent ME2 2AH
+ GB
+
+70-B3-D5 (hex) Airthings
+53C000-53CFFF (base 16) Airthings
+ Wergelandsveien 7
+ Oslo 0167
+ NO
+
+70-B3-D5 (hex) FRAKO Kondensatoren und Anlagenbau GmbH
+014000-014FFF (base 16) FRAKO Kondensatoren und Anlagenbau GmbH
+ Tscheulinstr. 21a
+ Teningen 79331
+ DE
+
+70-B3-D5 (hex) SANYU SWITCH CO., LTD.
+F14000-F14FFF (base 16) SANYU SWITCH CO., LTD.
+ Muro 1639-2
+ Kikuchi-gun Ohzu-cho Kumamoto-pref. 869-1235
+ JP
+
+70-B3-D5 (hex) MEDEX
+B4A000-B4AFFF (base 16) MEDEX
+ 240 Allée Jacques Monod
+ Saint-Priest France 69800
+ FR
+
+70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme
+17F000-17FFFF (base 16) MB connect line GmbH Fernwartungssysteme
+ Winnettener Straße 6
+ Dinkelsbühl Bavaria 91550
+ DE
+
+70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme
+B39000-B39FFF (base 16) MB connect line GmbH Fernwartungssysteme
+ Winnettener Straße 5
+ Dinkelsbühl Bavaria 91550
+ DE
+
+70-B3-D5 (hex) ESPAI DE PRODUCCIÓ I ELECTRÓNI
+162000-162FFF (base 16) ESPAI DE PRODUCCIÓ I ELECTRÓNI
+ C/Johannes Gutenberg, 4 y 6
+ Paterna Valencia 46980
+ ES
+
+70-B3-D5 (hex) Dia-Stron Limited
+EA8000-EA8FFF (base 16) Dia-Stron Limited
+ Unit 9 Focus Way
+ Andover Hampshire SP10 5NY
+ GB
+
+70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme
+5F9000-5F9FFF (base 16) MB connect line GmbH Fernwartungssysteme
+ Winnettener Straße 6
+ Dinkelsbuehl Bavaria 91550
+ DE
+
+70-B3-D5 (hex) Amfitech ApS
+123000-123FFF (base 16) Amfitech ApS
+ Platzvej 2
+ Vejle Syddanmark 7100
+ DK
+
+70-B3-D5 (hex) Den Automation
+0BF000-0BFFFF (base 16) Den Automation
+ Unit 6.05, Metropolitan Wharf
+ London E1W 3SS
+ GB
+
+70-B3-D5 (hex) YUYAMA MFG Co.,Ltd
+9C7000-9C7FFF (base 16) YUYAMA MFG Co.,Ltd
+ 3-3-1
+ TOYONAKASHI OSAKA 561-0841
+ JP
+
+70-B3-D5 (hex) Grossenbacher Systeme AG
+758000-758FFF (base 16) Grossenbacher Systeme AG
+ Spinnereistrasse 10
+ St. Gallen 9008
+ CH
+
+70-B3-D5 (hex) LEGENDAIRE TECHNOLOGY CO., LTD.
+02F000-02FFFF (base 16) LEGENDAIRE TECHNOLOGY CO., LTD.
+ 2F,No.278,Fu Shun Rd.
+ Taichung City 40764
+ TW
+
+70-B3-D5 (hex) TECNOWATT
+B1F000-B1FFFF (base 16) TECNOWATT
+ Via dell'Aeronautica
+ Bergamo 24035
+ IT
+
+70-B3-D5 (hex) Honeywell
+F4D000-F4DFFF (base 16) Honeywell
+ Aerospace - ETS
+ Clearwater Florida 33764
+ US
+
+70-B3-D5 (hex) Incusense
+7F5000-7F5FFF (base 16) Incusense
+ 424 NE 4th st
+ McMinnville OR 97128
+ US
+
+70-B3-D5 (hex) Aldridge Electrical Industries
+848000-848FFF (base 16) Aldridge Electrical Industries
+ 10-16 Sir Joseph Banks Drive
+ Sydney NSW 2231
+ AU
+
+70-B3-D5 (hex) Onosokki Co.,Ltd
+8C6000-8C6FFF (base 16) Onosokki Co.,Ltd
+ 3-9-3 shinyokohama,kohoku
+ yokohama 222-8507
+ JP
+
+70-B3-D5 (hex) csintech
+DB6000-DB6FFF (base 16) csintech
+ 234, Oksan-ro
+ Bucheon-si Gyeonggi-do 14521
+ KR
+
+70-B3-D5 (hex) RCD Radiokomunikace
+225000-225FFF (base 16) RCD Radiokomunikace
+ U Posty 26
+ Stare Hradiste 53352
+ CZ
+
+70-B3-D5 (hex) Roboteq
+DA5000-DA5FFF (base 16) Roboteq
+ 7812 E Acoma dr
+ Scottsdale AZ 85260
+ US
+
+70-B3-D5 (hex) CAMEON S.A.
+235000-235FFF (base 16) CAMEON S.A.
+ 3 rue de la Bavière
+ La Chapelle sur Erdre Loire-Atlantique 44240
+ FR
+
+70-B3-D5 (hex) Computech International
+280000-280FFF (base 16) Computech International
+ 525 Northern Boulevard
+ Great Neck NY 11021
+ US
+
+70-B3-D5 (hex) OS42 UG (haftungsbeschraenkt)
+9D1000-9D1FFF (base 16) OS42 UG (haftungsbeschraenkt)
+ Wachtelstrasse 81
+ Hamburg 22305
+ DE
+
+70-B3-D5 (hex) Adeli
+E61000-E61FFF (base 16) Adeli
+ Route de Sandrans
+ Saint Trivier sur Moignans Ain 01990
+ FR
+
+70-B3-D5 (hex) ATT Nussbaum Prüftechnik GmbH
+2A3000-2A3FFF (base 16) ATT Nussbaum Prüftechnik GmbH
+ Robert-Koch-Str. 35
+ Kehl-Auenheim 77694
+ DE
+
+70-B3-D5 (hex) Vibrationmaster
+C35000-C35FFF (base 16) Vibrationmaster
+ Rue Du Commerce, Technoport 3A
+ FOETZ 3895
+ LU
+
+70-B3-D5 (hex) Smart Vision Lights
+BCB000-BCBFFF (base 16) Smart Vision Lights
+ 2359 Holton Rd
+ Muskegon MI 49445
+ US
+
+70-B3-D5 (hex) Season Electronics Ltd
+15E000-15EFFF (base 16) Season Electronics Ltd
+ 600 Nest Business Park
+ Havant Hampshire PO9 5TL
+ GB
+
+70-B3-D5 (hex) ACCEL CORP
+53D000-53DFFF (base 16) ACCEL CORP
+ 16-32 Nakamachi
+ CHINO Nagano 3910005
+ JP
+
+70-B3-D5 (hex) HoseoTelnet Inc...
+11B000-11BFFF (base 16) HoseoTelnet Inc...
+ Hoseo Plaza B/D 7F, 416, Gangseo-ro, Gangseo-gu
+ Seoul 07583
+ KR
+
70-B3-D5 (hex) EMAC, Inc.
8AB000-8ABFFF (base 16) EMAC, Inc.
2390 EMAC Way
@@ -12374,12 +13118,6 @@ B3E000-B3EFFF (base 16) Paradigm Communication Systems Ltd
Alton Hants GU34 2PP
GB
-70-B3-D5 (hex) MB Connect Line GmbH
-161000-161FFF (base 16) MB Connect Line GmbH
- Winnettener Straße 6
- Dinkelsbühl Bavaria 91550
- DE
-
70-B3-D5 (hex) Sailmon BV
033000-033FFF (base 16) Sailmon BV
Vlierweg 22
@@ -14909,9 +15647,6 @@ C16000-C16FFF (base 16) Southern Innovation
Bellville Western Cape 7530
ZA
-70-B3-D5 (hex) Private
-E22000-E22FFF (base 16) Private
-
70-B3-D5 (hex) Comrod AS
408000-408FFF (base 16) Comrod AS
Fiskaaveien 1
@@ -15080,12 +15815,6 @@ F19000-F19FFF (base 16) Vitro Technology Corporation
Austin TX 78709-1232
US
-70-B3-D5 (hex) Riegl Laser Measurement Systems GmbH
-F10000-F10FFF (base 16) Riegl Laser Measurement Systems GmbH
- Riedenburgstrasse 48
- Horn Lower Austria 3580
- AT
-
70-B3-D5 (hex) M.T. S.R.L.
141000-141FFF (base 16) M.T. S.R.L.
VIA MONZA 83
@@ -15161,18 +15890,18 @@ EBC000-EBCFFF (base 16) Refine Technology, LLC
Vélizy-Villacoublay 78140
FR
-70-B3-D5 (hex) EN ElectronicNetwork Hamburg GmbH
-015000-015FFF (base 16) EN ElectronicNetwork Hamburg GmbH
- Meiendorfer Strasse 205
- Hamburg 22145
- DE
-
70-B3-D5 (hex) VITEC
05E000-05EFFF (base 16) VITEC
99 rue pierre sémard
Chatillon France 92320
FR
+70-B3-D5 (hex) EN ElectronicNetwork Hamburg GmbH
+015000-015FFF (base 16) EN ElectronicNetwork Hamburg GmbH
+ Meiendorfer Strasse 205
+ Hamburg 22145
+ DE
+
70-B3-D5 (hex) Saankhya Labs Private Limited
CA3000-CA3FFF (base 16) Saankhya Labs Private Limited
Embassy Icon, 3rd Floor, No. 3, Infantry Road,
@@ -15184,3 +15913,192 @@ D6E000-D6EFFF (base 16) ard sa
Micropolis Bat Clematis
Gap France 05000
FR
+
+70-B3-D5 (hex) Orlaco Products B.V.
+240000-240FFF (base 16) Orlaco Products B.V.
+ Albert Plesmanstraat 42
+ Barneveld 3772MN
+ NL
+
+70-B3-D5 (hex) FRS GmbH & Co. KG
+F8A000-F8AFFF (base 16) FRS GmbH & Co. KG
+ Weingartenstr. 1-3
+ Dortmund NW 44263
+ DE
+
+70-B3-D5 (hex) Liteon Technology Corporation
+073000-073FFF (base 16) Liteon Technology Corporation
+ 8F, 866, Chung-Cheng Road, Chung Ho
+ New Taipei City Taiwan 23585
+ TW
+
+70-B3-D5 (hex) ADVEEZ
+7EE000-7EEFFF (base 16) ADVEEZ
+ 12 RUE MICHEL LABROUSSE, BATIMENT 6
+ toulouse FRANCE 31100
+ FR
+
+70-B3-D5 (hex) Guangzhou Moblin Technology Co., Ltd.
+E52000-E52FFF (base 16) Guangzhou Moblin Technology Co., Ltd.
+ 35 Tianshou Rd, Tianhe District
+ Guangzhou Guangdong 510000
+ CN
+
+70-B3-D5 (hex) Fen Systems Ltd
+B1E000-B1EFFF (base 16) Fen Systems Ltd
+ 110 Cromwell Road
+ Cambridge CB1 3EG
+ GB
+
+70-B3-D5 (hex) SoFiHa
+78F000-78FFFF (base 16) SoFiHa
+ Hagenower Strasee 73
+ Schwerin 19061
+ DE
+
+70-B3-D5 (hex) PCSC
+515000-515FFF (base 16) PCSC
+ 3541 Challenger St.
+ Torrance CA 90503
+ US
+
+70-B3-D5 (hex) Microtronics Engineering GmbH
+D24000-D24FFF (base 16) Microtronics Engineering GmbH
+ Hauptstrasse 7
+ Ruprechtshofen 3244
+ AT
+
+70-B3-D5 (hex) Okolab Srl
+BF9000-BF9FFF (base 16) Okolab Srl
+ Via G. di Prisco n. 152
+ Ottaviano NA 80044
+ IT
+
+70-B3-D5 (hex) Acrodea, Inc.
+406000-406FFF (base 16) Acrodea, Inc.
+ 3F, Daisan Yamada Bldg., 22 Aizumi-cho
+ Shinjuku-ku Tokyo 1600005
+ JP
+
+70-B3-D5 (hex) Akse srl
+09A000-09AFFF (base 16) Akse srl
+ Via Aldo Moro, 39
+ Reggio Emilia Italy 42124
+ IT
+
+70-B3-D5 (hex) Argon ST
+A9E000-A9EFFF (base 16) Argon ST
+ 12701 Fair Lakes Circle
+ Fairfax VA 22033
+ US
+
+70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme
+161000-161FFF (base 16) MB connect line GmbH Fernwartungssysteme
+ Winnettener Straße 6
+ Dinkelsbühl Bavaria 91550
+ DE
+
+70-B3-D5 (hex) Hagiwara Solutions Co., Ltd.
+3C4000-3C4FFF (base 16) Hagiwara Solutions Co., Ltd.
+ 2-5-12 Nishiki, Naka-ku
+ Nagoya-shi Aichi-ken 460-0003
+ JP
+
+70-B3-D5 (hex) RZB Rudolf Zimmermann, Bamberg GmbH
+D71000-D71FFF (base 16) RZB Rudolf Zimmermann, Bamberg GmbH
+ Rheinstraße 16
+ Bamberg Bavaria 96052
+ DE
+
+70-B3-D5 (hex) EDCO Technology 1993 ltd
+B9C000-B9CFFF (base 16) EDCO Technology 1993 ltd
+ 10 hamelacha street
+ Rosh haayin 4809118
+ IL
+
+70-B3-D5 (hex) CoreKinect
+84C000-84CFFF (base 16) CoreKinect
+ 5024 S. Ash Ave, Suite 101
+ Tempe AZ 85282
+ US
+
+70-B3-D5 (hex) Wit.com Inc
+434000-434FFF (base 16) Wit.com Inc
+ 1251 Park Ave
+ Emeryville CA 94608
+ US
+
+70-B3-D5 (hex) Riegl Laser Measurement Systems GmbH
+F10000-F10FFF (base 16) Riegl Laser Measurement Systems GmbH
+ Riedenburgstraße 48
+ Horn Niederösterreich A-3580
+ AT
+
+70-B3-D5 (hex) PKE Electronics AG
+61E000-61EFFF (base 16) PKE Electronics AG
+ Computerstraße, 6
+ Wien Wien 1100
+ AT
+
+70-B3-D5 (hex) PT. Emsonic Indonesia
+360000-360FFF (base 16) PT. Emsonic Indonesia
+ Jl.Timor Blok E5, MM2100 Industrial Town Jatiwangi Cikarang Barat
+ Bekasi Jawa Barat 17530
+ ID
+
+70-B3-D5 (hex) H3D, Inc.
+3F2000-3F2FFF (base 16) H3D, Inc.
+ 812 Avis Drive
+ Ann Arbor MI 48108
+ US
+
+70-B3-D5 (hex) TATTILE SRL
+ACB000-ACBFFF (base 16) TATTILE SRL
+ VIA DONIZETTI, 1/3/5
+ MAIRANO BRESCIA 25030
+ IT
+
+70-B3-D5 (hex) Private
+E22000-E22FFF (base 16) Private
+
+70-B3-D5 (hex) Globalcom Engineering SPA
+636000-636FFF (base 16) Globalcom Engineering SPA
+ Via Volta 39
+ CARDANO AL CAMPO VA 21010
+ IT
+
+70-B3-D5 (hex) Code Blue Corporation
+A8D000-A8DFFF (base 16) Code Blue Corporation
+ 259 Hedcor Street
+ Holland MI 49423
+ US
+
+70-B3-D5 (hex) CDR SRL
+F58000-F58FFF (base 16) CDR SRL
+ VIA DEGLI ARTIGIANI 6
+ GINESTRA FIORENTINA FLORENCE 50055
+ IT
+
+70-B3-D5 (hex) DEUTA-WERKE GmbH
+F84000-F84FFF (base 16) DEUTA-WERKE GmbH
+ Paffrather Str. 140
+ Bergisch Gladbach North Rhine-Westphalia 51465
+ DE
+
+70-B3-D5 (hex) Sicon srl
+7C7000-7C7FFF (base 16) Sicon srl
+ Via Sila 1/3
+ Isola Vicentina Vicenza 36033
+ IT
+
+70-B3-D5 (hex) Sun Creative (ZheJiang) Technology INC.
+2B2000-2B2FFF (base 16) Sun Creative (ZheJiang) Technology INC.
+ 3#Building No.181 Wuchang street
+ HANGZHOU ZHE JIANG 310023
+ CN
+
+70-B3-D5 (hex) BASF Corporation
+680000-680FFF (base 16) BASF Corporation
+ 26 Davis Drive
+ Research Triangle Park NC 27709
+ US
diff --git a/hwdb/meson.build b/hwdb/meson.build
index d333ee68a3..158292c712 100644
--- a/hwdb/meson.build
+++ b/hwdb/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
hwdb_files = files('''
20-pci-vendor-model.hwdb
@@ -26,6 +11,7 @@ hwdb_files = files('''
20-acpi-vendor.hwdb
20-OUI.hwdb
20-net-ifname.hwdb
+ 20-vmbus-class.hwdb
60-evdev.hwdb
60-keyboard.hwdb
60-sensor.hwdb
diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py
index f4cc9c6974..4900a25778 100755
--- a/hwdb/parse_hwdb.py
+++ b/hwdb/parse_hwdb.py
@@ -2,10 +2,7 @@
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: MIT
#
-# This file is part of systemd. It is distrubuted under the MIT license, see
-# below.
-#
-# Copyright 2016 Zbigniew Jędrzejewski-Szmek
+# This file is distributed under the MIT license, see below.
#
# The MIT License (MIT)
#
diff --git a/hwdb/pci.ids b/hwdb/pci.ids
index 27cca09d2b..40ee143fc5 100644
--- a/hwdb/pci.ids
+++ b/hwdb/pci.ids
@@ -1,8 +1,8 @@
#
# List of PCI ID's
#
-# Version: 2018.02.19
-# Date: 2018-02-19 03:15:01
+# Version: 2018.06.11
+# Date: 2018-06-11 03:15:02
#
# Maintained by Albert Pool, Martin Mares, and other volunteers from
# the PCI ID Project at http://pci-ids.ucw.cz/.
@@ -25,6 +25,24 @@
0010 Allied Telesis, Inc (Wrong ID)
# This is a relabelled RTL-8139
8139 AT-2500TX V3 Ethernet
+0014 Loongson Technology LLC
+ 7a00 Hyper Transport Bridge Controller
+ 7a02 APB (Advanced Peripheral Bus) Controller
+ 7a03 Gigabit Ethernet Controller
+ 7a04 OTG USB Controller
+ 7a05 Vivante GPU (Graphics Processing Unit)
+ 7a06 DC (Display Controller)
+ 7a07 HDA (High Definition Audio) Controller
+ 7a08 SATA AHCI Controller
+ 7a09 PCI-to-PCI Bridge
+ 7a0b SPI Controller
+ 7a0c LPC Controller
+ 7a0f DMA (Direct Memory Access) Controller
+ 7a14 EHCI USB Controller
+ 7a15 Vivante GPU (Graphics Processing Unit)
+ 7a19 PCI-to-PCI Bridge
+ 7a24 OHCI USB Controller
+ 7a29 PCI-to-PCI Bridge
001c PEAK-System Technik GmbH
0001 PCAN-PCI CAN-Bus controller
001c 0004 2 Channel CAN Bus SJC1000
@@ -62,6 +80,7 @@
000a TTP-Monitoring Card V2.0
0432 SCM Microsystems, Inc.
0001 Pluto2 DVB-T Receiver for PCMCIA [EasyWatch MobilSet]
+0497 Dell Inc. (wrong ID)
0675 Dynalink
1700 IS64PH ISDN Adapter
1702 IS64PH ISDN Adapter
@@ -409,6 +428,7 @@
17aa 1052 ThinkServer RAID 720i
17aa 1053 ThinkServer RAID 720ix
1d49 0600 ThinkSystem RAID 730-8i 1GB Cache PCIe 12Gb Adapter
+ 1d49 0609 ThinkSystem RAID 730-8i 4GB Flash PCIe 12Gb Adapter
8086 351e RMS3CC080 RAID Controller
8086 351f RMS3CC040 RAID Controller
8086 9360 RS3DC080 RAID Controller
@@ -752,10 +772,10 @@
131b Kaveri [Radeon R4 Graphics]
131c Kaveri [Radeon R7 Graphics]
131d Kaveri [Radeon R6 Graphics]
- 15dd Raven Bridge [Radeon Vega Series / Radeon Vega Mobile Series]
+ 15dd Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series]
103c 83c6 Radeon Vega 8 Mobile
1458 d000 Radeon RX Vega 11
- 15ff Vega [Radeon Vega 28 Mobile]
+ 15ff Vega 11 [Radeon Vega 28 Mobile]
1714 BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series]
103c 168b ProBook 4535s
3150 RV380/M24 [Mobility Radeon X600]
@@ -846,7 +866,7 @@
434d IXP AC'97 Modem
4353 SMBus
4354 215CT [Mach64 CT PCI]
- 4358 210888CX [Mach64 CX]
+ 4358 Mach64 CX [Graphics Xpression]
4361 IXP SB300 AC'97 Audio Controller
4363 SMBus
436e 436E Serial ATA Controller
@@ -1047,7 +1067,7 @@
4437 RS250 [Mobility Radeon 7000 IGP]
4554 210888ET [Mach64 ET]
4654 Mach64 VT
- 4742 3D Rage PRO AGP 2X
+ 4742 Rage 3 [3D Rage PRO AGP 2X]
1002 0040 Rage Pro Turbo AGP 2X
1002 0044 Rage Pro Turbo AGP 2X
1002 0061 Rage Pro AIW AGP 2X
@@ -1063,7 +1083,7 @@
1028 c082 Rage Pro Turbo AGP 2X
8086 4152 Xpert 98D AGP 2X
8086 464a Rage Pro Turbo AGP 2X
- 4744 3D Rage PRO AGP 1X
+ 4744 Rage 3 [3D Rage PRO AGP 1X]
1002 4744 Rage Pro Turbo AGP
8086 4d55 Rage 3D Pro AGP 1X [Intel MU440EX]
4749 3D Rage PRO PCI
@@ -1087,7 +1107,7 @@
1002 0080 Rage Pro Turbo
1002 0084 Rage Pro Turbo
1002 4750 Rage Pro Turbo
- 4752 Rage XL PCI
+ 4752 Rage 3 [Rage XL PCI]
0e11 001e Proliant Rage XL
1002 0008 Rage XL
1002 4752 Proliant Rage XL
@@ -1109,19 +1129,19 @@
8086 5744 S845WD1-E mainboard
4753 Rage XC
1002 4753 Rage XC
- 4754 3D Rage II/II+ PCI [Mach64 GT]
- 4755 Mach64 GTB [3D Rage II+ DVD]
- 4756 3D Rage IIC PCI [Mach64 GT IIC]
+ 4754 Mach64 GT/GT-B [3D Rage I/II]
+ 4755 Mach64 GT-B [3D Rage II+ DVD]
+ 4756 Rage 2 [3D Rage IIC PCI]
1002 4756 Rage IIC
- 4757 3D Rage IIC AGP
+ 4757 Rage 2 [3D Rage IIC AGP]
1002 4757 Rage IIC AGP
1028 0089 Rage 3D IIC
1028 008e PowerEdge 1300 onboard video
1028 4082 Rage 3D IIC
1028 8082 Rage 3D IIC
1028 c082 Rage 3D IIC
- 4758 210888GX [Mach64 GX PCI]
- 4759 3D Rage IIC PCI
+ 4758 Mach64 GX [WinTurbo]
+ 4759 Rage 3 [3D Rage IIC PCI]
475a 3D Rage IIC AGP
1002 0084 Rage 3D Pro AGP 2x XPERT 98
1002 0087 Rage 3D IIC
@@ -1157,7 +1177,7 @@
4b69 R481 [Radeon X850 XT AGP] (Secondary)
4b6b R481 [Radeon X850 PRO AGP] (Secondary)
4b6c R481 [Radeon X850 XT Platinum Edition AGP] (Secondary)
- 4c42 3D Rage LT PRO AGP 2X
+ 4c42 Mach64 LT [3D Rage LT PRO AGP]
0e11 b0e7 Rage LT Pro (Compaq Presario 5240)
0e11 b0e8 Rage 3D LT Pro
0e11 b10e 3D Rage LT Pro (Compaq Armada 1750)
@@ -1185,9 +1205,9 @@
1028 00bb Latitude CPx
1179 ff00 Satellite 1715XCDS laptop
13bd 1019 PC-AR10
- 4c50 3D Rage LT PRO PCI
+ 4c50 Rage 3 LT [3D Rage LT PRO PCI]
1002 4c50 Rage LT Pro
- 4c52 Rage Mobility-M1 PCI
+ 4c52 M1 [Rage Mobility-M1 PCI]
1033 8112 Versa Note VXi
4c54 264LT [Mach64 LT]
4c57 RV200/M7 [Mobility Radeon 7500]
@@ -1255,7 +1275,7 @@
5044 All-In-Wonder 128 PCI
1002 0028 Rage 128 AIW
1002 0029 Rage 128 AIW
- 5046 Rage 128 PRO AGP 4x TMDS
+ 5046 Rage 4 [Rage 128 PRO AGP 4X TMDS]
1002 0004 Rage Fury Pro
1002 0008 Rage Fury Pro/Xpert 2000 Pro
1002 0014 Rage Fury Pro
@@ -1355,7 +1375,7 @@
1002 0028 Rage 128 AIW
1002 0029 Rage 128 AIW
1002 0068 Rage 128 AIW
- 5246 Rage Fury/Xpert 128/Xpert 2000 AGP 2x
+ 5246 Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP]
1002 0004 Magnum/Xpert 128/Xpert 99
1002 0008 Magnum/Xpert128/X99/Xpert2000
1002 0028 Rage 128 AIW AGP
@@ -1413,10 +1433,10 @@
5653 RV410/M26 [Mobility Radeon X700]
1025 0080 Aspire 5024WLMi
103c 0940 Compaq NW8240 Mobile Workstation
- 5654 264VT [Mach64 VT]
+ 5654 Mach64 VT [Video Xpression]
1002 5654 Mach64VT Reference
5655 264VT3 [Mach64 VT3]
- 5656 264VT4 [Mach64 VT4]
+ 5656 Mach64 VT4 [Video Xpression+]
5657 RV410 [Radeon X550 XTX / X700]
5830 RS300 Host Bridge
5831 RS300 Host Bridge
@@ -1603,6 +1623,7 @@
6602 Mars
6603 Mars
6604 Opal XT [Radeon R7 M265/M365X/M465]
+ 1025 0776 Aspire V5 Radeon R7 M265
103c 8006 FirePro M4170
103c 814f Litho XT [Radeon R7 M365X]
103c 82aa Litho XT [Radeon R7 M465]
@@ -1695,6 +1716,12 @@
17aa 368f Radeon R5 A230
6667 Jet ULT [Radeon R5 M230]
666f Sun LE [Radeon HD 8550M / R5 M230]
+ 66a0 Vega 20 [Radeon Instinct]
+ 66a1 Vega 20
+ 66a2 Vega 20
+ 66a3 Vega 20
+ 66a7 Vega 20
+ 66af Vega 20
6704 Cayman PRO GL [FirePro V7900]
6707 Cayman LE GL [FirePro V5900]
6718 Cayman XT [Radeon HD 6970]
@@ -2295,15 +2322,23 @@
67cc Ellesmere [Polaris10]
67cf Ellesmere [Polaris10]
67d0 Ellesmere [Radeon Pro V7300X / V7350x2]
- 67df Ellesmere [Radeon RX 470/480/570/580]
+ 67df Ellesmere [Radeon RX 470/480/570/570X/580/580X]
1002 0b37 Radeon RX 480
+ 1028 1722 Radeon RX 570X
+ 1028 1723 Radeon RX 580X
1043 04a8 Radeon RX 480
1043 04b0 Radeon RX 470
1043 04fb Radeon RX 480
1043 04fd Radeon RX 480 8GB
+ 106b 0161 Radeon Pro 580
+ 106b 0162 Radeon Pro 575
+ 106b 0163 Radeon Pro 570
1458 22f0 Radeon RX 570
+ 1458 22f7 Radeon RX 570 Gaming 4G
1462 3411 Radeon RX 470
1462 3413 Radeon RX 480
+ 1462 3416 Radeon RX 570
+ 1462 3418 Radeon RX 580 Armor 4G OC
148c 2372 Radeon RX 480
148c 2373 Radeon RX 470
1682 9470 Radeon RX 470
@@ -2313,6 +2348,7 @@
174b e349 Radeon RX 470
1787 a470 Radeon RX 470
1787 a480 Radeon RX 480
+ 1849 5001 Phantom Gaming X RX 580 OC
1da2 e353 Sapphire Radeon RX 580 Pulse 8GB
1da2 e366 Nitro+ Radeon RX 580 4GB
67e0 Baffin [Radeon Pro WX 4170]
@@ -2331,15 +2367,19 @@
103c 8277 Radeon Pro WX 4150
67e9 Baffin [Polaris11]
67eb Baffin [Radeon Pro V5300X]
- 67ef Baffin [Radeon RX 460/560D / Pro 450/455/460/560]
+ 67ef Baffin [Radeon RX 460/560D / Pro 450/455/460/555/560]
106b 0160 Radeon Pro 460
106b 0166 Radeon Pro 455
106b 0167 Radeon Pro 450
106b 0179 Radeon Pro 560
+ 106b 017a Radeon Pro 555
1642 1727 Polaris 21 XL [Radeon RX 560D]
1682 956d Polaris 21 XL [Radeon RX 560D]
- 67ff Baffin [Radeon RX 550 640SP / RX 560]
+ 67ff Baffin [Radeon RX 550 640SP / RX 560/560X]
1002 0b04 Radeon RX 560
+ 1028 1721 Radeon RX 560X
+ 1028 1726 Radeon RX 560DX
+ 103c 8479 Radeon RX 560X Mobile
1043 04bc Radeon RX 560
1458 22ed Radeon RX 560
148c 2381 Radeon RX 560
@@ -2767,7 +2807,7 @@
17aa 3928 Mobility Radeon HD 5650
17aa 3951 Mobility Radeon HD 5650
17aa 3977 Radeon HD 6550M
- 68c7 Madison [Mobility Radeon HD 5570/6550A]
+ 68c7 Pinewood [Mobility Radeon HD 5570/6550A]
1462 2241 Mobility Radeon HD 5570
1462 2243 Mobility Radeon HD 5570
1462 2244 Mobility Radeon HD 5570
@@ -3082,9 +3122,15 @@
6986 Polaris12
6987 Lexa [Radeon E9171 MCM]
6995 Lexa XT [Radeon PRO WX 2100]
- 699f Lexa PRO [Radeon RX 550]
+ 699f Lexa PRO [Radeon RX 550/550X]
+ 1028 1720 Radeon RX 550X
148c 2380 Lexa XL [Radeon RX 550]
1da2 e367 Lexa PRO [Radeon RX 550]
+ 69a0 Vega 12
+ 69a1 Vega 12
+ 69a2 Vega 12
+ 69a3 Vega 12
+ 69af Vega 12
700f RS100 AGP Bridge
7010 RS200/RS250 AGP Bridge
7100 R520 [Radeon X1800 XT]
@@ -3364,11 +3410,13 @@
9553 RV710/M92 [Mobility Radeon HD 4530/4570/545v]
1025 015e Mobility Radeon HD 4570
1025 017d Mobility Radeon HD 4570
- 1025 0205 Mobility Radeon HD 4570
+ 1025 0205 Mobility Radeon HD 4570 / 545v
1025 0206 Mobility Radeon HD 4570
1025 0237 Mobility Radeon HD 4570
- 1028 02be Mobility Radeon HD 4570
+ 1028 02be Mobility Radeon HD 4570 / 545v
1028 02e8 Mobility Radeon HD 4530
+ 103c 143c Mobility Radeon HD 545v
+ 103c 1446 Mobility Radeon HD 545v
103c 3624 Mobility Radeon HD 4530
103c 3628 Mobility Radeon HD 4530
103c 3636 Mobility Radeon HD 4530
@@ -3376,6 +3424,12 @@
1043 1b42 Mobility Radeon HD 4570
104d 9056 Mobility Radeon HD 4570
1179 ff82 Satellite L505-13T GPU (Mobility Radeon HD 5145)
+ 144d c07f Mobility Radeon HD 545v
+ 144d c571 Mobility Radeon HD 545v
+ 1462 1006 Mobility Radeon HD 545v
+ 17aa 2129 Mobility Radeon HD 545v
+ 17aa 215b Mobility Radeon HD 545v
+ 17aa 21bb Mobility Radeon HD 545v
9555 RV710/M92 [Mobility Radeon HD 4350/4550]
103c 1411 ProBook 4720s GPU (Mobility Radeon HD 4350)
9557 RV711 GL [FirePro RG220]
@@ -3511,6 +3565,7 @@
17aa 5113 Radeon R6 Graphics
17aa 5116 Radeon R6 Graphics
17aa 5118 Radeon R5 Graphics
+ 98e4 Stoney [Radeon R2/R3/R4/R5 Graphics]
9900 Trinity [Radeon HD 7660G]
103c 1985 Pavilion 17-e163sg Notebook PC
# AMD A10-5800K CPU
@@ -4756,6 +4811,7 @@
102b 0f83 Millennium G550
102b 0f84 Millennium G550 Dual Head DDR 32Mb
102b 1e41 Millennium G550
+ 102b 22c0 G550 PCIe
102b 2300 Millennium G550 LP PCIE
2537 Millennium P650/P750
102b 1820 Millennium P750 64MB
@@ -5321,6 +5377,7 @@
4030 zx2 System Bus Adapter
4031 zx2 I/O Controller
4037 PCIe Local Bus Adapter
+ 9602 AMD RS780/RS880 PCI to PCI bridge (int gfx)
103e Solliday Engineering
103f Synopsys/Logic Modeling Group
1040 Accelgraphics Inc.
@@ -5830,7 +5887,7 @@
3070 Hitachi FIVE-FX Fibre Channel to PCIe HBA
3505 SH7751 PCI Controller (PCIC)
350e SH7751R PCI Controller (PCIC)
-1055 Efar Microsystems
+1055 Microchip Technology / SMSC
9130 SLC90E66 [Victory66] IDE
9460 SLC90E66 [Victory66] ISA
9462 SLC90E66 [Victory66] USB
@@ -6256,15 +6313,19 @@
1644 FastLinQ QL45000 Series 100GbE Controller
1077 e4f8 FastLinQ QL45611H 100GbE Adapter
1654 FastLinQ QL45000 Series 50GbE Controller
+ 1077 0032 QL45212 Flex 50Gb 2-port Ethernet Adapter
1590 0223 Synergy 6810C 25/50Gb Ethernet Adapter
1656 FastLinQ QL45000 Series 25GbE Controller
+ 1077 0033 QL45214 Flex 25Gb 4-port Ethernet Adapter
1077 02a7 QL45212-DE 25GbE Adapter
1077 e4f6 FastLinQ QL45211H 25GbE Adapter
1077 e4f7 FastLinQ QL45212H 25GbE Adapter
165c FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE)
+ 1077 0034 QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE
1077 e4f1 FastLinQ QL45462H 40GbE FCoE Adapter
1077 e4f2 FastLinQ QL45461H 40GbE FCoE Adapter
165e FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI)
+ 1077 0034 QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE
1077 e4f1 FastLinQ QL45462H 40GbE iSCSI Adapter
1077 e4f2 FastLinQ QL45461H 40GbE iSCSI Adapter
1664 FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF)
@@ -6362,13 +6423,16 @@
8070 FastLinQ QL41000 Series 10/25/40/50GbE Controller
1077 0001 10GE 2P QL41162HxRJ-DE Adapter
1077 0002 10GE 2P QL41112HxCU-DE Adapter
+ 1077 0004 4x10GE QL41164HFCU CNA
1077 0005 QLogic 4x10GE QL41164HMRJ CNA
1077 0006 QLogic 4x10GE QL41164HMCU CNA
1077 0007 QLogic 2x1GE+2x10GE QL41264HMCU CNA
1077 0009 QLogic 2x1GE+2x10GE QL41162HMRJ CNA
1077 000b 25GE 2P QL41262HxCU-DE Adapter
- 1077 0011 FastLinQ QL41212H 25GbE Adapter
+ 1077 0011 FastLinQ QL41212HLCU 25GbE Adapter
1077 0012 FastLinQ QL41112H 10GbE Adapter
+ 1077 0019 QL41232HOCU - Dual Port 25/10GbE SFP28 OCP Adapter
+ 1077 0039 QLogic QL41262 PCIe 25Gb 2-Port SFP28 Ethernet Adapter
1590 021d 10/25GbE 2P QL41222HLCU-HP Adapter
1590 021e 10/25GbE 2P QL41162HMRJ-HP Adapter
1590 021f 10/25GbE 2P QL41262HMCU-HP Adapter
@@ -6376,6 +6440,7 @@
8080 FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE)
1077 0001 10GE 2P QL41162HxRJ-DE Adapter
1077 0002 10GE 2P QL41112HxCU-DE Adapter
+ 1077 0004 4x10GE QL41164HFCU CNA
1077 0005 QLogic 4x10GE QL41164HMRJ CNA
1077 0006 QLogic 4x10GE QL41164HMCU CNA
1077 0007 QLogic 2x1GE+2x10GE QL41264HMCU CNA
@@ -6387,6 +6452,8 @@
8084 FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI)
1077 0001 10GE 2P QL41162HxRJ-DE Adapter
1077 0002 10GE 2P QL41112HxCU-DE Adapter
+ 1077 0003 4x10GE QL41164HxRJ CNA
+ 1077 0004 4x10GE QL41164HFCU CNA
1077 0005 QLogic 4x10GE QL41164HMRJ CNA
1077 0006 QLogic 4x10GE QL41164HMCU CNA
1077 0007 QLogic 2x25GE QL41262HMCU CNA
@@ -6398,6 +6465,8 @@
8090 FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF)
1077 0001 25GE 2P QL41262HxCU-DE Adapter
1077 0002 10GE 2P QL41112HxCU-DE Adapter
+ 1077 0003 4x10GE QL41164HxRJ CNA
+ 1077 0004 4x10GE QL41164HFCU CNA
1077 0005 QLogic 4x10GE QL41164HMRJ CNA
1077 0006 QLogic 4x10GE QL41164HMCU CNA
1077 0007 QLogic 2x1GE+2x10GE QL41264HMCU CNA
@@ -8310,8 +8379,10 @@
0100 Lightning 1200
10dd 0023 Lightning 1200 15+16M
10de NVIDIA Corporation
- 0008 NV1 [EDGE 3D]
- 0009 NV1 [EDGE 3D]
+ 0008 NV1 [STG2000X-B Series]
+ 0009 NV1 [NV1 Series]
+ 0018 NV3 [Riva 128]
+ 0019 NV3 [Riva 128ZX]
0020 NV4 [Riva TNT]
1043 0200 V3400 TNT
1048 0c18 Erazor II SGRAM
@@ -8582,7 +8653,7 @@
0098 G70M [GeForce Go 7800]
0099 G70M [GeForce Go 7800 GTX]
009d G70GL [Quadro FX 4500]
- 00a0 NV5 [Aladdin TNT2]
+ 00a0 NV0A [Aladdin TNT2 IGP]
14af 5810 Maxi Gamer Xentor
00c0 NV41 [GeForce 6800 GS]
00c1 NV41 [GeForce 6800]
@@ -8678,16 +8749,16 @@
00f5 G71 [GeForce 7800 GS]
00f6 NV43 [GeForce 6800 GS/XT]
1682 217e XFX GeForce 6800 XTreme 256MB DDR3 AGP
- 00f8 NV40GL [Quadro FX 3400/4400]
+ 00f8 NV45GL [Quadro FX 3400/4400]
00f9 NV40 [GeForce 6800 GT/GTO/Ultra]
10de 00f9 NV40 [GeForce 6800 GT]
1682 2120 GEFORCE 6800 GT PCI-E
- 00fa NV36 [GeForce PCX 5750]
- 00fb NV38 [GeForce PCX 5900]
+ 00fa NV39 [GeForce PCX 5750]
+ 00fb NV35 [GeForce PCX 5900]
00fc NV37GL [Quadro FX 330/GeForce PCX 5300]
00fd NV37GL [Quadro PCI-E Series]
00fe NV38GL [Quadro FX 1300]
- 00ff NV18 [GeForce PCX 4300]
+ 00ff NV19 [GeForce PCX 4300]
0100 NV10 [GeForce 256 SDR]
1043 0200 AGP-V6600 SGRAM
1043 0201 AGP-V6600 SDRAM
@@ -9896,7 +9967,7 @@
0863 C79 [GeForce 9400M]
106b 00aa MacBook5,1
0864 C79 [GeForce 9300]
- 0865 C79 [GeForce 9300/ION]
+ 0865 C79 [GeForce 9300 / ION]
0866 C79 [GeForce 9400M G]
106b 00b1 GeForce 9400M
0867 C79 [GeForce 9400]
@@ -9920,12 +9991,12 @@
1043 1c12 GeForce G102M
1043 1c52 GeForce G205M
0874 C79 [ION]
- 0876 ION VGA [GeForce 9400M]
+ 0876 C79 [GeForce 9400M / ION]
087a C79 [GeForce 9400]
- 087d ION VGA
+ 087d C79 [ION]
19da a123 IONITX-F-E
- 087e ION LE VGA
- 087f ION LE VGA
+ 087e C79 [ION LE]
+ 087f C79 [ION LE]
08a0 MCP89 [GeForce 320M]
08a2 MCP89 [GeForce 320M]
08a3 MCP89 [GeForce 320M]
@@ -9956,6 +10027,7 @@
0a64 GT218 [ION]
0a65 GT218 [GeForce 210]
1043 8334 EN210 SILENT
+ 1458 36a9 GV-N210D3-1GI (rev. 6.0/6.1)
1462 8094 N210 [Geforce 210] PCIe graphics adapter
0a66 GT218 [GeForce 310]
0a67 GT218 [GeForce 315]
@@ -9966,7 +10038,7 @@
1028 040b Latitude E6510
17aa 2142 ThinkPad T410
0a6e GT218M [GeForce 305M]
- 0a6f GT218 [ION]
+ 0a6f GT218M [ION]
0a70 GT218M [GeForce 310M]
0a71 GT218M [GeForce 305M]
0a72 GT218M [GeForce 310M]
@@ -9974,7 +10046,7 @@
0a74 GT218M [GeForce G210M]
1b0a 903a GeForce G210
0a75 GT218M [GeForce 310M]
- 0a76 GT218 [ION 2]
+ 0a76 GT218M [ION 2]
0a78 GT218GL [Quadro FX 380 LP]
0a7a GT218M [GeForce 315M]
104d 907e GeForce 315M
@@ -10246,6 +10318,7 @@
0fc0 GK107 [GeForce GT 640 OEM]
0fc1 GK107 [GeForce GT 640]
0fc2 GK107 [GeForce GT 630 OEM]
+ 0fc5 GK107
0fc6 GK107 [GeForce GTX 650]
1043 8428 GTX650-DC-1GD5
0fc8 GK107 [GeForce GT 740]
@@ -10351,6 +10424,7 @@
1040 GF119 [GeForce GT 520]
1043 83a0 ENGT520 SILENT
1042 GF119 [GeForce 510]
+ 1045 GF119
1048 GF119 [GeForce 605]
1049 GF119 [GeForce GT 620 OEM]
104a GF119 [GeForce GT 610]
@@ -10811,6 +10885,7 @@
11b6 GK104GLM [Quadro K3100M]
11b7 GK104GLM [Quadro K4100M]
11b8 GK104GLM [Quadro K5100M]
+ 11b9 GK104GLM
11ba GK104GL [Quadro K5000]
11bb GK104GL [Quadro 4100]
11bc GK104GLM [Quadro K5000M]
@@ -10894,6 +10969,7 @@
1288 GK208B [GeForce GT 720]
1289 GK208 [GeForce GT 710]
128b GK208B [GeForce GT 710]
+ 1043 85f7 GT710-SL-1GD5
1290 GK208M [GeForce GT 730M]
103c 2afa GeForce GT 730A
103c 2b04 GeForce GT 730A
@@ -11039,6 +11115,7 @@
1b01 GP102
1b02 GP102 [TITAN Xp]
1b06 GP102 [GeForce GTX 1080 Ti]
+ 1b07 GP102 [P102-100]
1b30 GP102GL [Quadro P6000]
1b38 GP102GL [Tesla P40]
1b70 GP102GL
@@ -11046,7 +11123,7 @@
1b80 GP104 [GeForce GTX 1080]
1b81 GP104 [GeForce GTX 1070]
1b82 GP104 [GeForce GTX 1070 Ti]
- 1b83 GP104
+ 1b83 GP104 [GeForce GTX 1060 6GB]
1b84 GP104 [GeForce GTX 1060 3GB]
1b87 GP104 [P104-100]
1ba0 GP104M [GeForce GTX 1080 Mobile]
@@ -11065,6 +11142,8 @@
1bb7 GP104GLM [Quadro P4000 Mobile]
1462 11e9 Quadro P4000 Max-Q
1bb8 GP104GLM [Quadro P3000 Mobile]
+ 1bb9 GP104GLM [Quadro P4200 Mobile]
+ 1bbb GP104GLM [Quadro P3200 Mobile]
1bc7 GP104 [P104-101]
1be0 GP104M [GeForce GTX 1080 Mobile]
1028 07c0 GeForce GTX 1080 Max-Q
@@ -11089,7 +11168,7 @@
1c61 GP106M [GeForce GTX 1050 Ti Mobile]
1c62 GP106M [GeForce GTX 1050 Mobile]
1c70 GP106GL
- 1c80 GP107
+ 1c80 GP107 [GeForce GTX 1050 3GB]
1c81 GP107 [GeForce GTX 1050]
1c82 GP107 [GeForce GTX 1050 Ti]
1c8c GP107M [GeForce GTX 1050 Ti Mobile]
@@ -11102,12 +11181,22 @@
1cb2 GP107GL [Quadro P600]
1cb3 GP107GL [Quadro P400]
1cb6 GP107GL [Quadro P620]
+ 1cba GP107GLM [Quadro P2000 Mobile]
+ 1cbb GP107GLM [Quadro P1000 Mobile]
+ 1cbc GP107GLM [Quadro P600 Mobile]
1d01 GP108 [GeForce GT 1030]
1d10 GP108M [GeForce MX150]
- 1d33 GP108GL [Quadro P500]
+ 1d12 GP108M [GeForce MX150]
+ 1d72 1701 Mi Notebook Pro [GeForce MX150]
+ 1d33 GP108GLM [Quadro P500 Mobile]
1d81 GV100 [TITAN V]
- 1db1 GV100GL [Tesla V100 SXM2]
- 1db4 GV100GL [Tesla V100 PCIe]
+ 1db1 GV100GL [Tesla V100 SXM2 16GB]
+ 1db3 GV100GL [Tesla V100 FHHL 16GB]
+ 1db4 GV100GL [Tesla V100 PCIe 16GB]
+ 1db5 GV100GL [Tesla V100 SXM2 32GB]
+ 1db6 GV100GL [Tesla V100 PCIe 32GB]
+ 1db7 GV100GL [Tesla V100 DGXS 32GB]
+ 1dba GV100GL [Quadro GV100]
10df Emulex Corporation
0720 OneConnect NIC (Skyhawk)
103c 1934 FlexFabric 20Gb 2-port 650M Adapter
@@ -12490,12 +12579,13 @@
111b Teledyne Electronic Systems
111c Tricord Systems Inc.
0001 Powerbis Bridge
-111d Integrated Device Technology, Inc. [IDT]
+# now owned by Microchip Technology
+111d Microsemi / PMC / IDT
0001 IDT77201/77211 155Mbps ATM SAR Controller [NICStAR]
0003 IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller
0004 IDT77V252 155Mbps ATM MICRO ABR SAR Controller
0005 IDT77V222 155Mbps ATM MICRO ABR SAR Controller
- 8018 PES12N3A PCI Express Switch
+ 8018 PES12N3A 12-lane 3-Port PCI Express Switch
801c PES24N3A PCI Express Switch
8028 PES4T4 PCI Express Switch
802b PES8T5A PCI Express Switch
@@ -12544,9 +12634,14 @@
1093 75ff PXIe-8383mc DMA
1093 7600 PXIe-8383mc DMA
1093 7602 PXIe-8384
+# 32-lanes 24-ports Gen.2
+ 808a 89HPES32NT24BG2 PCI Express Switch
+# 32-lanes 24-ports Gen.2
+ 808c 89HPES32NT24AG2 PCI Express Switch
808e PES24NT24G2 PCI Express Switch
-# 32 port / 8 lane PCIe Gen 2 packet switch
- 808f PES32NT8AG2
+ 808f 89HPES32NT8AG2 32-Lane 8-Port PCIe Gen2 System Interconnect Switch with Non-Transparent Bridging
+ 8090 89HPES16NT16G2 16-Lane 16-Port PCIe Gen2 System Interconnect Switch
+ 8092 89HPES12NT12G2 12-Lane 12-Port PCIe Gen2 System Interconnect Switch
80cf F32P08xG3 [PCIe boot mode]
80d2 F32P08xG3 NVMe controller
111e Eldec
@@ -13369,6 +13464,8 @@
1170 Inventec Corporation
1171 Loughborough Sound Images Plc
1172 Altera Corporation
+ 00a7 Stratix V
+ 0530 Stratix IV
1173 Adobe Systems, Inc
1174 Bridgeport Machines
1175 Mitron Computer Inc.
@@ -13509,6 +13606,7 @@
1028 01d7 XPS M1210
1028 01f3 Inspiron 1420
1028 022f Inspiron 1525
+ 103c 1521 HP EliteBook 8540w
103c 30b5 Presario V3242AU
103c 30b7 Presario V6133CL
103c 30cc Pavilion dv6700
@@ -13560,6 +13658,7 @@
1028 01f5 Inspiron 1501
1028 024f Latitude e6500
103c 03b5 Presario V3242AU
+ 103c 1521 HP EliteBook 8540w
103c 30b7 Presario V6133CL
103c 30cf Pavilion dv9500/9600/9700 series
1183 0843 Alienware Aurora m9700
@@ -14241,10 +14340,11 @@
7384 PM7384 [FREEDM - 84P672 Frm Engine & Datalink Mgr]
8000 PM8000 [SPC - SAS Protocol Controller]
8009 PM8009 SPCve 8x6G
- 8032 ATTO Celerity FC8xEN
+ 8032 PM8032 Tachyon QE8
117c 003a Celerity FC-81EN Fibre Channel Adapter
117c 003b Celerity FC-82EN Fibre Channel Adapter
117c 003c Celerity FC-84EN Fibre Channel Adapter
+ 117c 403b ThunderLink FC 1082 Fibre Channel Adapter
8053 PM8053 SXP 12G 24-port SAS/SATA expander
8054 PM8054 SXP 12G 36-port SAS/SATA expander
8055 PM8055 SXP 12G 48-port SAS/SATA expander
@@ -14369,7 +14469,6 @@
0001 Roadrunner serial HIPPI
1210 Hyperparallel Technologies
1211 Braintech Inc
-1212 Kingston Technology Corp.
1213 Applied Intelligent Systems, Inc.
1214 Performance Technologies, Inc.
1215 Interware Co., Ltd
@@ -14537,7 +14636,8 @@
0d13 Desktop PCI L1/L3 Telephony
1232 GPT Limited
1233 Bus-Tech, Inc.
-1235 Risq Modular Systems, Inc.
+# nee Risq Modular Systems, Inc.
+1235 SMART Modular Technologies
1236 Sigma Designs Corporation
0000 RealMagic64/GX
6401 REALmagic 64/GX (SD 6425)
@@ -15006,6 +15106,7 @@
8872 IT887xF PCI to ISA I/O chip with SMB, GPIO, Serial or Parallel Port
8888 IT8888F/G PCI to ISA Bridge with SMB [Golden Gate]
8889 IT8889F PCI to ISA Bridge
+ 8892 IT8892E PCIe to PCI Bridge
8893 IT8893E PCIe to PCI Bridge
e886 IT8330G
1284 Sahara Networks, Inc.
@@ -15059,7 +15160,7 @@
12a2 Newgen Systems Corporation
12a3 Lucent Technologies
8105 T8105 H100 Digital Switch
-12a4 NTT Electronics Technology Company
+12a4 NTT Electronics Corporation
12a5 Vision Dynamics Ltd.
12a6 Scalable Networks, Inc.
12a7 AMO GmbH
@@ -15538,6 +15639,9 @@
5163 RealSSD P425m
5180 9100 PRO NVMe SSD
5181 9100 MAX NVMe SSD
+ 5190 9200 ECO NVMe SSD
+ 5191 9200 PRO NVMe SSD
+ 5192 9200 MAX NVMe SSD
1345 Arescom Inc
1347 Odetics
1349 Sumitomo Electric Industries, Ltd.
@@ -16513,6 +16617,9 @@
5016 T580-OCP-SO Unified Wire Ethernet Controller
5017 T520-OCP-SO Unified Wire Ethernet Controller
5018 T540-BT Unified Wire Ethernet Controller
+ 5019 T540-LP-BT Unified Wire Ethernet Controller
+ 501a T540-SO-BT Unified Wire Ethernet Controller
+ 501b T540-SO-CR Unified Wire Ethernet Controller
5080 T540-5080 Unified Wire Ethernet Controller
5081 T540-5081 Unified Wire Ethernet Controller
5082 T504-5082 Unified Wire Ethernet Controller
@@ -16552,6 +16659,7 @@
50aa T580-50AA Unified Wire Ethernet Controller
50ab T520-50AB Unified Wire Ethernet Controller
50ac T540-50AC Unified Wire Ethernet Controller
+ 50ad T520-50AD Unified Wire Ethernet Controller
5401 T520-CR Unified Wire Ethernet Controller
5402 T522-CR Unified Wire Ethernet Controller
5403 T540-CR Unified Wire Ethernet Controller
@@ -16576,6 +16684,9 @@
5416 T580-OCP-SO Unified Wire Ethernet Controller
5417 T520-OCP-SO Unified Wire Ethernet Controller
5418 T540-BT Unified Wire Ethernet Controller
+ 5419 T540-LP-BT Unified Wire Ethernet Controller
+ 541a T540-SO-BT Unified Wire Ethernet Controller
+ 541b T540-SO-CR Unified Wire Ethernet Controller
5480 T540-5080 Unified Wire Ethernet Controller
5481 T540-5081 Unified Wire Ethernet Controller
5482 T504-5082 Unified Wire Ethernet Controller
@@ -16615,6 +16726,7 @@
54aa T580-50AA Unified Wire Ethernet Controller
54ab T520-50AB Unified Wire Ethernet Controller
54ac T540-50AC Unified Wire Ethernet Controller
+ 54ad T520-50AD Unified Wire Ethernet Controller
5501 T520-CR Unified Wire Storage Controller
5502 T522-CR Unified Wire Storage Controller
5503 T540-CR Unified Wire Storage Controller
@@ -16639,6 +16751,9 @@
5516 T580-OCP-SO Unified Wire Storage Controller
5517 T520-OCP-SO Unified Wire Storage Controller
5518 T540-BT Unified Wire Storage Controller
+ 5519 T540-LP-BT Unified Wire Storage Controller
+ 551a T540-SO-BT Unified Wire Storage Controller
+ 551b T540-SO-CR Unified Wire Storage Controller
5580 T540-5080 Unified Wire Storage Controller
5581 T540-5081 Unified Wire Storage Controller
5582 T504-5082 Unified Wire Storage Controller
@@ -16678,6 +16793,7 @@
55aa T580-50AA Unified Wire Storage Controller
55ab T520-50AB Unified Wire Storage Controller
55ac T540-50AC Unified Wire Storage Controller
+ 55ad T520-50AD Unified Wire Storage Controller
5601 T520-CR Unified Wire Storage Controller
5602 T522-CR Unified Wire Storage Controller
5603 T540-CR Unified Wire Storage Controller
@@ -16702,6 +16818,9 @@
5616 T580-OCP-SO Unified Wire Storage Controller
5617 T520-OCP-SO Unified Wire Storage Controller
5618 T540-BT Unified Wire Storage Controller
+ 5619 T540-LP-BT Unified Wire Storage Controller
+ 561a T540-SO-BT Unified Wire Storage Controller
+ 561b T540-SO-CR Unified Wire Storage Controller
5680 T540-5080 Unified Wire Storage Controller
5681 T540-5081 Unified Wire Storage Controller
5682 T504-5082 Unified Wire Storage Controller
@@ -16741,6 +16860,7 @@
56aa T580-50AA Unified Wire Storage Controller
56ab T520-50AB Unified Wire Storage Controller
56ac T540-50AC Unified Wire Storage Controller
+ 56ad T520-50AD Unified Wire Storage Controller
5701 T520-CR Unified Wire Ethernet Controller
5702 T522-CR Unified Wire Ethernet Controller
5703 T540-CR Unified Wire Ethernet Controller
@@ -16804,6 +16924,9 @@
5816 T580-OCP-SO Unified Wire Ethernet Controller [VF]
5817 T520-OCP-SO Unified Wire Ethernet Controller [VF]
5818 T540-BT Unified Wire Ethernet Controller [VF]
+ 5819 T540-LP-BT Unified Wire Ethernet Controller [VF]
+ 581a T540-SO-BT Unified Wire Ethernet Controller [VF]
+ 581b T540-SO-CR Unified Wire Ethernet Controller [VF]
5880 T540-5080 Unified Wire Ethernet Controller [VF]
5881 T540-5081 Unified Wire Ethernet Controller [VF]
5882 T504-5082 Unified Wire Ethernet Controller [VF]
@@ -16843,6 +16966,7 @@
58aa T580-50AA Unified Wire Ethernet Controller [VF]
58ab T520-50AB Unified Wire Ethernet Controller [VF]
58ac T540-50AC Unified Wire Ethernet Controller [VF]
+ 58ad T520-50AD Unified Wire Ethernet Controller [VF]
6001 T6225-CR Unified Wire Ethernet Controller
6002 T6225-SO-CR Unified Wire Ethernet Controller
6003 T6425-CR Unified Wire Ethernet Controller
@@ -16864,6 +16988,8 @@
6085 T6240-6085 Unified Wire Ethernet Controller
6086 T6225-6086 Unified Wire Ethernet Controller
6087 T6225-6087 Unified Wire Ethernet Controller
+ 6088 T62100-6088 Unified Wire Ethernet Controller
+ 6089 T62100-6089 Unified Wire Ethernet Controller
6401 T6225-CR Unified Wire Ethernet Controller
6402 T6225-SO-CR Unified Wire Ethernet Controller
6403 T6425-CR Unified Wire Ethernet Controller
@@ -16885,6 +17011,8 @@
6485 T6240-6085 Unified Wire Ethernet Controller
6486 T6225-6086 Unified Wire Ethernet Controller
6487 T6225-6087 Unified Wire Ethernet Controller
+ 6488 T62100-6088 Unified Wire Ethernet Controller
+ 6489 T62100-6089 Unified Wire Ethernet Controller
6501 T6225-CR Unified Wire Storage Controller
6502 T6225-SO-CR Unified Wire Storage Controller
6503 T6425-CR Unified Wire Storage Controller
@@ -16906,6 +17034,8 @@
6585 T6240-6085 Unified Wire Storage Controller
6586 T6225-6086 Unified Wire Storage Controller
6587 T6225-6087 Unified Wire Storage Controller
+ 6588 T62100-6088 Unified Wire Storage Controller
+ 6589 T62100-6089 Unified Wire Storage Controller
6601 T6225-CR Unified Wire Storage Controller
6602 T6225-SO-CR Unified Wire Storage Controller
6603 T6425-CR Unified Wire Storage Controller
@@ -16927,6 +17057,8 @@
6685 T6240-6085 Unified Wire Storage Controller
6686 T6225-6086 Unified Wire Storage Controller
6687 T6225-6087 Unified Wire Storage Controller
+ 6688 T62100-6088 Unified Wire Storage Controller
+ 6689 T62100-6089 Unified Wire Storage Controller
6801 T6225-CR Unified Wire Ethernet Controller [VF]
6802 T6225-SO-CR Unified Wire Ethernet Controller [VF]
6803 T6425-CR Unified Wire Ethernet Controller [VF]
@@ -16948,6 +17080,8 @@
6885 T6240-6085 Unified Wire Ethernet Controller [VF]
6886 T6225-6086 Unified Wire Ethernet Controller [VF]
6887 T6225-6087 Unified Wire Ethernet Controller [VF]
+ 6888 T62100-6088 Unified Wire Ethernet Controller [VF]
+ 6889 T62100-6089 Unified Wire Ethernet Controller [VF]
a000 PE10K Unified Wire Ethernet Controller
1426 Storage Technology Corp.
1427 Better On-Line Solutions
@@ -17021,6 +17155,7 @@
a800 XP941 PCIe SSD
a802 NVMe SSD Controller SM951/PM951
a804 NVMe SSD Controller SM961/PM961
+ a808 NVMe SSD Controller SM981/PM981
a820 NVMe SSD Controller 171X
1028 1f95 Express Flash NVMe XS1715 SSD 400GB
1028 1f96 Express Flash NVMe XS1715 SSD 800GB
@@ -17037,7 +17172,7 @@
1028 1fc1 Express Flash NVMe PM1725 800GB SFF
1028 1fc2 Express Flash NVMe PM1725 1.6TB SFF
1028 1fc4 Express Flash NVMe PM1725 1.6TB AIC
- a822 NVMe SSD Controller 172Xa
+ a822 NVMe SSD Controller 172Xa/172Xb
1014 0621 PCIe3 1.6TB NVMe Flash Adapter II x8
1014 0622 PCIe3 3.2TB NVMe Flash Adapter II x8
1014 0629 PCIe3 6.4TB NVMe Flash Adapter II x8
@@ -17048,6 +17183,14 @@
1028 1fdd Express Flash PM1725a 1.6TB AIC
1028 1fde Express Flash PM1725a 3.2TB AIC
1028 1fdf Express Flash PM1725a 6.4TB AIC
+ 1028 1ff3 Express Flash PM1725b 1.6TB SFF
+ 1028 1ff4 Express Flash PM1725b 3.2TB SFF
+ 1028 1ff5 Express Flash PM1725b 6.4TB SFF
+ 1028 1ff6 Express Flash PM1725b 12.8TB SFF
+ 1028 1ff7 Express Flash PM1725b 1.6TB AIC
+ 1028 1ff8 Express Flash PM1725b 3.2TB AIC
+ 1028 1ff9 Express Flash PM1725b 6.4TB AIC
+ 1028 1ffa Express Flash PM1725b 12.8TB AIC
144e OLITEC
144f Askey Computer Corp.
1450 Octave Communications Ind.
@@ -17544,6 +17687,7 @@
1680 NetXtreme BCM5761e Gigabit Ethernet PCIe
1681 NetXtreme BCM5761 Gigabit Ethernet PCIe
1682 NetXtreme BCM57762 Gigabit Ethernet PCIe
+ 106b 00f6 Thunderbolt to Gigabit Ethernet Adapter
1683 NetXtreme BCM57767 Gigabit Ethernet PCIe
1684 NetXtreme BCM5764M Gigabit Ethernet PCIe
1685 NetXtreme II BCM57500S Gigabit Ethernet
@@ -17718,8 +17862,9 @@
16d5 BCM57407 NetXtreme-E 10GBase-T Ethernet Controller
16d6 BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller
16d7 BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller
- 14e4 1202 BCM957412M4122 OCP 1x25G Type1 wRoCE
- 14e4 1404 BCM957414M4142 OCP 2x25G Type1 wRoCE
+ 14e4 1202 BCM957412M4122C OCP 1x25G Type1 wRoCE
+ 14e4 1402 BCM957414A4142CC 10Gb/25Gb Ethernet PCIe
+ 14e4 1404 BCM957414M4142C OCP 2x25G Type1 wRoCE
1590 020e Ethernet 25Gb 2-port 631SFP28 Adapter
1590 0211 Ethernet 25Gb 2-port 631FLR-SFP28 Adapter
16d8 BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller
@@ -18691,10 +18836,8 @@
020f MT28908A0 Family [ConnectX-6 Flash Recovery]
0210 MT28908A0 Family [ConnectX-6 Secure Flash Recovery]
0211 MT416842 Family [BlueField SoC Flash Recovery]
-# reserved for RM#105916
024e MT53100 [Spectrum-2, Flash recovery mode]
-# Actual value to be used
- 024f MT53100 [Spectrum-2, Flash recovery mode]
+ 024f MT53100 [Spectrum-2, Secure Flash recovery mode]
0262 MT27710 [ConnectX-4 Lx Programmable] EN
0263 MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN
0264 Innova-2 Flex Burn image
@@ -18711,6 +18854,7 @@
15b3 0026 ConnectX-3 IB FDR Dual Port Mezzanine Card
15b3 0028 ConnectX-3 VPI Dual QSFP+ Port QDR Infiniband 40Gb/s or 10Gb Ethernet
15b3 0059 ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Mezzanine Card
+ 15b3 0064 ConnectX-3 EN 10/40 GbE Single Port QSFP+ Adapter (MCX313A-BCBT)
15b3 0065 ConnectX-3 VPI IB FDR/40 GbE Dual Port QSFP+ Adapter
15b3 0066 ConnectX-3 IB FDR10 Dual Port Mezzanine Card
15b3 0067 ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Adapter
@@ -18759,10 +18903,9 @@
1014 MT27700 Family [ConnectX-4 Virtual Function]
1015 MT27710 Family [ConnectX-4 Lx]
15b3 0001 ConnectX-4 Lx EN network interface card, 25GbE single-port SFP28, PCIe3.0 x8, tall bracket, ROHS R6
- 15b3 0003 ConnectX-4 Lx EN network interface card, 25GbE dual-port SFP28, PCIe3.0 x8, tall bracket, ROHS R6
+ 15b3 0003 Stand-up ConnectX-4 Lx EN, 25GbE dual-port SFP28, PCIe3.0 x8, MCX4121A-ACAT
15b3 0004 ConnectX-4 Lx Stand-up dual-port 10GbE MCX4121A-XCAT
15b3 0005 Mellanox Technologies ConnectX-4 Lx Stand-up single-port 40GbE MCX4131A-BCAT
- 15b3 0016 ConnectX-4 Lx 25 GbE Dual Port SFP28 Adapter
15b3 0020 MCX4411A-ACQN, ConnectX-4 Lx EN OCP, 1x25Gb
15b3 0021 MCX4421A-ACQN ConnectX-4 Lx EN OCP,2x25G
15b3 0025 ConnectX-4 Lx 25 GbE Dual Port SFP28 rNDC
@@ -18791,12 +18934,13 @@
6278 MT25208 InfiniHost III Ex (Tavor compatibility mode)
6279 MT25208 [InfiniHost III Ex HCA Flash Recovery]
6282 MT25208 [InfiniHost III Ex]
- 6340 MT25408 [ConnectX VPI - IB SDR / 10GigE]
- 634a MT25418 [ConnectX VPI PCIe 2.0 2.5GT/s - IB DDR / 10GigE]
+ 6340 MT25408A0-FCC-SI ConnectX, Dual Port 10Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface
+ 634a MT25408A0-FCC-DI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface
+ 1014 1014 4X InfiniBand DDR Expansion Card (CFFh) for IBM BladeCenter
6368 MT25448 [ConnectX EN 10GigE, PCIe 2.0 2.5GT/s]
- 6372 MT25408 [ConnectX EN 10GigE 10GBaseT, PCIe 2.0 2.5GT/s]
- 6732 MT26418 [ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE]
- 673c MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE]
+ 6372 MT25458 ConnectX EN 10GBASE-T PCIe 2.5 GT/s
+ 6732 MT25408A0-FCC-GI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface
+ 673c MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface
1014 0415 PCIe2 2-port 4X InfiniBand QDR Adapter for Power
1014 0487 GX++ 1-port 4X IB QDR Adapter for Power 795
103c 1782 4X QDR InfiniBand Mezzanine HCA for c-Class BladeSystem
@@ -18805,11 +18949,12 @@
103c 1781 NC543i 1-port 4x QDR IB/Flex-10 10Gb Adapter
103c 3349 NC543i 2-port 4xQDR IB/10Gb Adapter
6750 MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s]
- 1014 0461 2-Port 10 GbE RoCE SR LP PCIe2 (rev b0)
+ 1014 0416 PCIe2 2-Port 10GbE RoCE SFP+ Adapter
+ 1014 0461 PCIe2 2-Port 10GbE RoCE SR Adapter
15b3 0018 HP 10 GbE PCI-e G2 Dual-Port NIC (rev C1)
# FC EC26
15b3 6572 IBM Flex System EN4132 2-port 10Gb RoCE Adapter
- 675a MT25408 [ConnectX EN 10GigE 10GBaseT, PCIe Gen2 5GT/s]
+ 675a MT26458 ConnectX EN 10GBASE-T PCIe Gen2 5.0 GT/s
6764 MT26468 [ConnectX EN 10GigE, PCIe 2.0 5GT/s Virtualization+]
103c 3313 NC542m Dual Port Flex-10 10GbE BLc Adapter
676e MT26478 [ConnectX EN 40GigE, PCIe 2.0 5GT/s]
@@ -19027,7 +19172,8 @@
5449 SmartPCI561 Modem
1641 MKNet Corp.
1642 Bitland(ShenZhen) Information Technology Co., Ltd.
-1657 Brocade Communications Systems, Inc.
+# nee Brocade Communications Systems, Inc.
+1657 Cavium QLogic
0013 425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA
103c 1742 82B 8Gbps dual port FC HBA
103c 1744 42B 4Gbps dual port FC HBA
@@ -19040,8 +19186,7 @@
103c 1743 81B 8Gbps single port FC HBA
1657 0014 415/815 4Gbps/8Gbps single port PCIe FC HBA
0021 804 8Gbps FC HBA for HP Bladesystem c-class
-# AnyIO Adapter
- 0022 1860 16Gbps/10Gbps Fabric Adapter
+ 0022 BR-1860 Fabric Adapter
1657 0022 10Gbps CNA - FCOE
1657 0023 10Gbps CNA - LL
1657 0024 16Gbps FC HBA
@@ -19388,6 +19533,7 @@
0040 QCA9980/9990 802.11ac Wireless Network Adapter
0041 QCA6164 802.11ac Wireless Network Adapter
0042 QCA9377 802.11ac Wireless Network Adapter
+ 0046 QCA9984 802.11ac Wave 2 Wireless Network Adapter
0050 QCA9887 802.11ac Wireless Network Adapter
0207 AR5210 Wireless Network Adapter [AR5000 802.11a]
1014 AR5212 802.11abg NIC
@@ -19422,6 +19568,7 @@
16b8 Sonnet Technologies, Inc.
16be Creatix Polymedia GmbH
16c3 Synopsys, Inc.
+ edda EPMockUp
16c6 Micrel-Kendin
8695 Centaur KS8695 ARM processor
8842 KSZ8842-PMQL 2-Port Ethernet Switch
@@ -19890,6 +20037,7 @@
1914 VirtexUS ASIC Emulation Board [DNVUF2A]
1915 Arria10 PCIe MainRef Design [DNPCIe_80G_A10_LL]
1916 VirtexUS PCIe Accelerator Board [DNVUF2_HPC_PCIe]
+ 1917 UltrascalePlus PCIe Accelerator Board [DNPCIe_400G_VU_LL]
1a00 Virtex6 PCIe DMA Netlist Design
1a01 Virtex6 PCIe Darklite Design [DNPCIe_HXT_10G_LL]
1a02 Virtex7 PCIe DMA Netlist Design
@@ -19900,6 +20048,8 @@
1a08 KintexUS PCIe Darklite Design [DNPCIe_40G_KU_LL_QSFP]
1a09 Arria10 PCIe Darklite Design [DNPCIe_80G_A10_LL]
1a0a VirtexUS PCIe Darklite Design [DNVUF2_HPC_PCIe]
+ 1a0b UltrascalePlus PCIe Darklite Design [DNPCIe_400G_VU_LL]
+ 1a0c KintexUS PCIe DRAM Packet Capture Design [DNPCIe_40G_KU_LL]
17e4 Sectra AB
0001 KK671 Cardbus encryption board
0002 KK672 Cardbus encryption board
@@ -20390,6 +20540,7 @@
0b03 SFC9250 10/25/40/50/100G Ethernet Controller
1924 801d x2522-R1 2000 Series 10/25G Adapter
1924 801e x2542-R1 2000 Series 40/100G Adapter
+ 1924 8022 x2522-R2 2000 Series 10/25G Adapter
1803 SFC9020 10G Ethernet Controller (Virtual Function)
1813 SFL9021 10GBASE-T Ethernet Controller (Virtual Function)
1903 SFC9120 10G Ethernet Controller (Virtual Function)
@@ -20694,7 +20845,51 @@
5808 DDRdrive X8
dd52 DDRdrive X1-30
19e5 Huawei Technologies Co., Ltd.
+# subvendor
+ 0123 ES3000 V3 NVMe PCIe SSD
+ 19e5 3022 NVMe SSD ES3600P V3 800GB 2.5" U.2
+ 19e5 3023 NVMe SSD ES3600P V3 1200GB 2.5" U.2
+ 19e5 3024 NVMe SSD ES3600P V3 1600GB 2.5" U.2
+ 19e5 3025 NVMe SSD ES3600P V3 2000GB 2.5" U.2
+ 19e5 3026 NVMe SSD ES3600P V3 3200GB 2.5" U.2
+ 19e5 3033 NVMe SSD ES3600C V3 1200GB HHHL AIC
+ 19e5 3034 NVMe SSD ES3600C V3 1600GB HHHL AIC
+ 19e5 3036 NVMe SSD ES3600C V3 3200GB HHHL AIC
+ 0200 Hi1822 Family (2*25GE)
+ 0201 Hi1822 Family (2*100GE)
+ 1710 iBMA Virtual Network Adapter
1711 Hi1710 [iBMC Intelligent Management system chip w/VGA support]
+ 1822 Hi1822 Family (4*25GE)
+ 371e Hi1822 Family Virtual Bridge
+ a120 HiSilicon PCIe Root Port with Gen4
+ a121 HiSilicon PCI-PCI Bridge
+ a122 HiSilicon Embedded DMA Engine
+ a124 HiSilicon Internal SDI Function Engine
+ a125 HiSilicon SDI Network Controller
+ a126 HiSilicon SDI NVMe Storage Controller
+ a127 HiSilicon SDI Accelerator
+ a12a HiSilicon Add-on PCI-PCI Bridge
+ a220 HNS GE Network Controller
+ a221 HNS GE/10GE/25GE Network Controller
+ a222 HNS GE/10GE/25GE RDMA Network Controller
+ a224 HNS GE/10GE/25GE/50GE RDMA Network Controller
+ a226 HNS GE/10GE/25GE/50GE/100GE RDMA Network Controller
+ a22a HiSilicon Network For SDI
+ a22e HNS Network Controller (Virtual Function)
+ a22f HNS RDMA Network Controller (Virtual Function)
+ a230 HiSilicon SAS 3.0 HBA
+ a235 HiSilicon AHCI HBA
+ a238 HiSilicon USB 3.0 Host Controller
+ a239 HiSilicon USB 2.0 2-port Host Controller
+ a23a HiSilicon USB 2.0 Host Controller
+ a250 HiSilicon ZIP Engine
+ a251 HiSilicon ZIP Engine(Virtual Function)
+ a255 HiSilicon SEC Engine
+ a256 HiSilicon SEC Engine(Virtual Function)
+ a258 HiSilicon HPRE Engine
+ a259 HiSilicon HPRE Engine(Virtual Function)
+ a25a HiSilicon RDE Engine
+ a25b HiSilicon RDE Engine(Virtual Function)
19e7 NET (Network Equipment Technologies)
1001 STIX DSP Card
1002 STIX - 1 Port T1/E1 Card
@@ -20746,14 +20941,16 @@
0200 TILE-Gx processor
0201 TILE-Gx Processor Virtual Function
2000 TILE-Gx PCI Express Root Port
-1a4a SLAC National Accelerator Lab PPA-REG
+1a4a SLAC National Accelerator Lab TID-AIR
1000 MCOR Power Supply Controller
1010 AMC EVR - Stockholm Timing Board
+ 1020 Cluster On Board (COB) Ethernet Switch
2000 PGPCard - 4 Lane
2001 PGPCard - 8 Lane Plus EVR
2010 PCI-Express EVR
# PC-260-101-03
2020 PGP-GEN3 PCIe
+ 2030 AXI Stream DAQ PCIe card
1a51 Hectronic AB
1a55 Rohde & Schwarz DVS GmbH
0010 SDStationOEM
@@ -20913,6 +21110,7 @@
1849 1080 Motherboard
1142 ASM1042A USB 3.0 Host Controller
1242 ASM1142 USB 3.1 Host Controller
+ 1343 ASM1143 USB 3.1 Host Controller
1b2c Opal-RT Technologies Inc.
1b36 Red Hat, Inc.
0001 QEMU PCI-PCI bridge
@@ -20998,8 +21196,8 @@
# 2xHDMI and 2xHD-SDI inputs
e5f4 MPEG2 and H264 Encoder-Transcoder
f1c4 Dual ASI-RX/TX-CI card
-1b66 Deltacast
- 0007 Delta-3G-elp-11 SDI I/O Board
+1b66 DELTACAST
+ 0007 DELTA-3G-elp-d
1b6f Etron Technology, Inc.
7023 EJ168 USB 3.0 Host Controller
7052 EJ188/EJ198 USB 3.0 Host Controller
@@ -21115,6 +21313,9 @@
# Used on V120 VME Crate Controller
1c32 Highland Technology, Inc.
1c33 Daktronics, Inc
+1c36 Annapurna Labs Ltd.
+ 0001 Gigabit Ethernet Adapter
+ 0002 SFP+ 10G Ethernet Adapter
1c3b Accensus, LLC
0200 Telas2
# http://www.accensusllc.com/accensustelas2.html
@@ -21141,6 +21342,7 @@
5100 EB5100
1c8a TSF5 Corporation
0001 Hunter PCI Express
+1c8c Mobiveil, Inc.
1cb1 Collion UG & Co.KG
1cb8 Dawning Information Industry Co., Ltd.
1cc5 Embedded Intelligence, Inc.
@@ -21252,12 +21454,14 @@
1d65 Imagine Communications Corp.
04de Taurus/McKinley
1d6a Aquantia Corp.
+ 0001 AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
07b1 AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
08b1 AQC108 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
11b1 AQC111 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
12b1 AQC112 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
87b1 AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
d107 AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
+ 1043 8741 XG-C100C
d108 AQC108 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion]
1d6c Atomic Rules LLC
1001 A5PL-E1
@@ -21277,6 +21481,7 @@
100e AR-ARKA-FX1 [Arkville 64B DPDK Data Mover]
1d6c 2001 DPDK-Aware Virtual Function [Arkville VF]
4200 A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument]
+1d72 Xiaomi
1d78 DERA
1d7c Aerotech, Inc.
1d87 Fuzhou Rockchip Electronics Co., Ltd
@@ -21314,6 +21519,7 @@
1d95 Graphcore Ltd
1da1 Teko Telecom S.r.l.
1da2 Sapphire Technology Limited
+1dbb NGD Systems, Inc.
1de1 Tekram Technology Co.,Ltd.
0391 TRM-S1040 [DC-315 / DC-395 series]
2020 DC-390
@@ -21335,6 +21541,8 @@
0001 ml605
0002 alst4
0003 alst4x
+1dfc JSC NT-COM
+ 1181 TDM 8 Port E1/T1/J1 Adapter
# nee Tumsan Oy
1fc0 Ascom (Finland) Oy
0300 E2200 Dual E1/Rawpipe Card
@@ -21385,7 +21593,7 @@
4027 TN9710P 10GBase-T/NBASE-T Ethernet Adapter
1154 0368 LGY-PCIE-MG
1432 8104 10 Gigabit Ethernet PCI Express Adapter
- 1546 4027 IOI9710P 10Gbase-T/NBASE-T Ethernet Adapter
+ 1546 4027 GE10-PCIE4XG202P 10Gbase-T/NBASE-T Ethernet Adapter
1fc9 3015 Ethernet Adapter
4527 TN9710Q 5GBase-T/NBASE-T Ethernet Adapter
1fcc StreamLabs
@@ -21405,10 +21613,11 @@
20f4 TRENDnet
2116 ZyDAS Technology Corp.
21c3 21st Century Computer Corp.
+22db Missing Link Electronics, Inc.
2304 Colorgraphic Communications Corp.
2348 Racore
2010 8142 100VG/AnyLAN
-2646 Kingston Technologies
+2646 Kingston Technology Company, Inc.
270b Xantel Corporation
270f Chaintech Computer Co. Ltd
2711 AVID Technology Inc.
@@ -22711,7 +22920,7 @@
0a2a Haswell-ULT Integrated Graphics Controller
0a2e Haswell-ULT Integrated Graphics Controller
0a53 DC P3520 SSD
- 0a54 Express Flash NVMe P4500
+ 0a54 Express Flash NVMe P4500/P4600
1028 1fe1 Express Flash NVMe 1TB 2.5" U.2 (P4500)
1028 1fe2 Express Flash NVMe 2TB 2.5" U.2 (P4500)
1028 1fe3 Express Flash NVMe 4TB 2.5" U.2 (P4500)
@@ -23170,7 +23379,7 @@
1057 PRO/100 VE Network Connection
1059 82551QM Ethernet Controller
105b 82546GB Gigabit Ethernet Controller (Copper)
- 105e 82571EB Gigabit Ethernet Controller
+ 105e 82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications)
103c 7044 NC360T PCI Express Dual Port Gigabit Server Adapter
103c 704e Dual Port 1000Base-T (PCIe) [AD337A]
1775 1100 CR11/VR11 Single Board Computer
@@ -23320,12 +23529,13 @@
8086 1093 PRO/1000 PT Desktop Adapter
10ba 80003ES2LAN Gigabit Ethernet Controller (Copper)
10bb 80003ES2LAN Gigabit Ethernet Controller (Serdes)
- 10bc 82571EB Gigabit Ethernet Controller (Copper)
+ 10bc 82571EB/82571GB Gigabit Ethernet Controller (Copper)
1014 0368 4-Port 10/100/1000 Base-TX PCI Express Adapter for POWER
103c 704b NC364T PCI Express Quad Port Gigabit Server Adapter
- 108e 11bc x4 PCI-Express Quad Gigabit Ethernet UTP Low Profile Adapter
+# 375-3481-01 REV:50
+ 108e 11bc Quad Port Adapter
8086 10bc PRO/1000 PT Quad Port LP Server Adapter
- 8086 11bc PRO/1000 PT Quad Port LP Server Adapter
+ 8086 11bc PRO/1000 PT Quad Port LP Server Adapter (Kirkwood Low Profile)
10bd 82566DM-2 Gigabit Network Connection
1028 0211 OptiPlex 755
10bf 82567LF Gigabit Network Connection
@@ -23885,9 +24095,11 @@
1563 Ethernet Controller 10G X550T
1028 1fa8 Ethernet 10G 4P X550/I350 rNDC
1028 1fa9 Ethernet 10G 4P X550 rNDC
+ 1170 0001 Intel Ethernet Controller X550-T2 OCP card
14c0 1201 X550 10Gb 2P RJ45 OCP Mezz
1590 00d1 Ethernet 10Gb 2-port 562T Adapter
1590 00d2 Ethernet 10Gb 2-port 562FLR-T Adapter
+ 16b8 7217 Twin10G Thunderbolt 3 Edition
18d4 0c08 X550 10Gb 2-port RJ45 OCP Mezz Card MOP81-I-10GT2
193d 1008 560T-B
193d 1009 560T-L
@@ -24026,6 +24238,7 @@
1059 0150 RD-01068 10GbE interface
15ab Ethernet Connection X552 10 GbE Backplane
15ac Ethernet Connection X552 10 GbE SFP+
+ 1059 0160 RD-01167 10GbE interface
15ad Ethernet Connection X552/X557-AT 10GBASE-T
15ae Ethernet Connection X552 1000BASE-T
15b0 Ethernet Connection X552 Backplane
@@ -24186,30 +24399,32 @@
e4bf 3100 CX1-BAND
1962 80960RM (i960RM) Microprocessor
105a 0000 SuperTrak SX6000 I2O CPU
- 19ac DNV SMBus Contoller - Host
- 19b0 DNV SATA Controller 0
- 19b1 DNV SATA Controller 0
- 19b2 DNV SATA Controller 0
- 19b3 DNV SATA Controller 0
- 19b4 DNV SATA Controller 0
- 19b5 DNV SATA Controller 0
- 19b6 DNV SATA Controller 0
- 19b7 DNV SATA Controller 0
- 19be DNV SATA Controller 0
- 19bf DNV SATA Controller 0
- 19c0 DNV SATA Controller 1
- 19c1 DNV SATA Controller 1
- 19c2 DNV SATA Controller 1
- 19c3 DNV SATA Controller 1
- 19c4 DNV SATA Controller 1
- 19c5 DNV SATA Controller 1
- 19c6 DNV SATA Controller 1
- 19c7 DNV SATA Controller 1
- 19ce DNV SATA Controller 1
- 19cf DNV SATA Controller 1
- 19dc DNV LPC or eSPI
- 19df DNV SMBus controller
- 19e0 DNV SPI Controller
+ 19ac Atom Processor C3000 Series SMBus Contoller - Host
+ 19b0 Atom Processor C3000 Series SATA Controller 0
+ 19b1 Atom Processor C3000 Series SATA Controller 0
+ 19b2 Atom Processor C3000 Series SATA Controller 0
+ 19b3 Atom Processor C3000 Series SATA Controller 0
+ 19b4 Atom Processor C3000 Series SATA Controller 0
+ 19b5 Atom Processor C3000 Series SATA Controller 0
+ 19b6 Atom Processor C3000 Series SATA Controller 0
+ 19b7 Atom Processor C3000 Series SATA Controller 0
+ 19be Atom Processor C3000 Series SATA Controller 0
+ 19bf Atom Processor C3000 Series SATA Controller 0
+ 19c0 Atom Processor C3000 Series SATA Controller 1
+ 19c1 Atom Processor C3000 Series SATA Controller 1
+ 19c2 Atom Processor C3000 Series SATA Controller 1
+ 19c3 Atom Processor C3000 Series SATA Controller 1
+ 19c4 Atom Processor C3000 Series SATA Controller 1
+ 19c5 Atom Processor C3000 Series SATA Controller 1
+ 19c6 Atom Processor C3000 Series SATA Controller 1
+ 19c7 Atom Processor C3000 Series SATA Controller 1
+ 19ce Atom Processor C3000 Series SATA Controller 1
+ 19cf Atom Processor C3000 Series SATA Controller 1
+ 19d0 Atom Processor C3000 Series USB 3.0 xHCI Controller
+ 19dc Atom Processor C3000 Series LPC or eSPI
+ 19df Atom Processor C3000 Series SMBus controller
+ 19e0 Atom Processor C3000 Series SPI Controller
+ 19e2 Atom Processor C3000 Series QuickAssist Technology
1a21 82840 840 [Carmel] Chipset Host Bridge (Hub A)
1a23 82840 840 [Carmel] Chipset AGP Bridge
1a24 82840 840 [Carmel] Chipset PCI Bridge (Hub B)
@@ -24423,6 +24638,7 @@
1d69 C604/X79 series chipset 4-Port SATA/SAS Storage Control Unit
1d6a C600/X79 series chipset Dual 4-Port SATA Storage Control Unit
1d6b C602 chipset 4-Port SATA Storage Control Unit
+ 0497 1028 Dell Precision T3600
1d6c C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit
1d6d C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit
1d6e C600/X79 series chipset Dual 4-Port SATA Storage Control Unit
@@ -27576,6 +27792,7 @@
372b Xeon C5500/C3500 Core
372c Xeon C5500/C3500 Reserved
373f Xeon C5500/C3500 IOxAPIC
+ 37c8 C62x Chipset QuickAssist Technology
37cd Ethernet Virtual Function 700 Series
37ce Ethernet Connection X722 for 10GbE backplane
1590 0215 Ethernet 10Gb 2-port 568i Adapter
@@ -27598,6 +27815,7 @@
17aa 4021 Ethernet Connection X722 for 1GbE
17aa 4022 Ethernet Connection X722 for 1GbE
37d2 Ethernet Connection X722 for 10GBASE-T
+ 1170 37d2 Ethernet Connection X722 for 10GBASE-T
14cd 0030 Ethernet OCP 2x10G RJ45 Phy Card [USI-X557-10GbaseT]
1590 0218 Ethernet 10Gb 2-port 568FLR-MMT Adapter
17aa 4020 Ethernet Connection X722 for 10GBASE-T
@@ -27969,6 +28187,17 @@
3cf4 Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 0
3cf5 Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 1
3cf6 Xeon E5/Core i7 System Address Decoder
+ 3e18 8th Gen Core Processor Host Bridge/DRAM Registers
+ 3e1f 8th Gen Core Processor Host Bridge/DRAM Registers
+ 3e81 8th Gen Core Processor PCIe Controller (x16)
+ 3e85 8th Gen Core Processor PCIe Controller (x8)
+ 3e89 8th Gen Core Processor PCIe Controller (x4)
+ 3e91 8th Gen Core Processor Gaussian Mixture Model
+ 3ec2 8th Gen Core Processor Host Bridge/DRAM Registers
+ 3ec4 8th Gen Core Processor Host Bridge/DRAM Registers
+ 3ec6 8th Gen Core Processor Host Bridge/DRAM Registers
+ 3eca 8th Gen Core Processor Host Bridge/DRAM Registers
+ 3ed0 8th Gen Core Processor Host Bridge/DRAM Registers
4000 5400 Chipset Memory Controller Hub
4001 5400 Chipset Memory Controller Hub
4003 5400 Chipset Memory Controller Hub
@@ -28275,6 +28504,7 @@
6f51 Xeon Processor D Family QuickData Technology Register DMA Channel 1
6f52 Xeon Processor D Family QuickData Technology Register DMA Channel 2
6f53 Xeon Processor D Family QuickData Technology Register DMA Channel 3
+ 6f54 Xeon Processor D Family QuickAssist Technology
6f60 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1
6f68 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS
6f6a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder
@@ -28881,6 +29111,7 @@
17aa 382a B51-80 Laptop
9d48 Sunrise Point-LP LPC Controller
1028 06f3 Latitude 3570
+ 9d4e Intel(R) 100 Series Chipset Family LPC Controller/eSPI Controller - 9D4E
9d56 Sunrise Point-LP LPC Controller
9d58 Sunrise Point-LP LPC Controller
17aa 2247 ThinkPad T570
@@ -29103,6 +29334,20 @@
a2ed 200 Series PCH PCI Express Root Port #23
a2ee 200 Series PCH PCI Express Root Port #24
a2f0 200 Series PCH HD Audio
+ a304 H370 Chipset LPC/eSPI Controller
+ a323 Cannon Lake PCH SMBus Controller
+ a324 Cannon Lake PCH SPI Controller
+ a32c Cannon Lake PCH PCI Express Root Port 21
+ a330 Cannon Lake PCH PCI Express Root Port 9
+ a342 Cannon Lake PCH PCI Express Root Port 19
+ a343 Cannon Lake PCH PCI Express Root Port 20
+ a348 Cannon Lake PCH cAVS
+ a352 Cannon Lake PCH SATA AHCI Controller
+ a360 Cannon Lake PCH HECI Controller
+ a36d Cannon Lake PCH USB 3.1 xHCI Host Controller
+ a36f Cannon Lake PCH Shared SRAM
+ a370 Wireless-AC 9560 [Jefferson Peak]
+ a379 Cannon Lake PCH Thermal Controller
a620 6400/6402 Advanced Memory Buffer (AMB)
abc0 Omni-Path Fabric Switch Silicon 100 Series
b152 21152 PCI-to-PCI Bridge
@@ -29140,6 +29385,7 @@
d156 Core Processor Semaphore and Scratchpad Registers
d157 Core Processor System Control and Status Registers
d158 Core Processor Miscellaneous Registers
+ f1a6 SSD Pro 7600p/760p/E 6100p Series
80ee InnoTek Systemberatung GmbH
beef VirtualBox Graphics Adapter
cafe VirtualBox Guest Service
@@ -29616,6 +29862,7 @@
# Parallel ports at BAR0,BAR2. Serial ports at BAR4-5
1000 0022 2P2S (2 Parallel / 2 16550A Serial Port Adapter)
9865 PCI 9865 Multi-I/O Controller
+ 9900 MCS9900 Multi-I/O Controller
9901 PCIe 9901 Multi-I/O Controller
9904 4-Port PCIe Serial Adapter
# 2-port Serial 1-port Parallel Adaptor
@@ -29795,6 +30042,8 @@ dcba Dynamic Engineering
004e PC104p-Biserial-III-NVY5
004f PC104p-Biserial-III-NVY6
0052 PCIeBiSerialDb37 BA22 LVDS IO
+# 8 port 16550 compatible UART, PMC format, RS-232 IO, RTS, CTS, DTR, DSR supported
+ 0066 PMC-OctalUART-232
dd01 Digital Devices GmbH
0003 Octopus DVB Adapter
dd01 0001 Octopus DVB adapter
@@ -29978,6 +30227,14 @@ C 00 Unclassified device
C 01 Mass storage controller
00 SCSI storage controller
01 IDE interface
+ 00 ISA Compatibility mode-only controller
+ 05 PCI native mode-only controller
+ 0a ISA Compatibility mode controller, supports both channels switched to PCI native mode
+ 0f PCI native mode controller, supports both channels switched to ISA compatibility mode
+ 80 ISA Compatibility mode-only controller, supports bus mastering
+ 85 PCI native mode-only controller, supports bus mastering
+ 8a ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering
+ 8f PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering
02 Floppy disk controller
03 IPI bus controller
04 RAID bus controller
@@ -30125,7 +30382,10 @@ C 0c Serial bus controller
04 Fibre Channel
05 SMBus
06 InfiniBand
- 07 IPMI SMIC interface
+ 07 IPMI Interface
+ 00 SMIC
+ 01 KCS
+ 02 BT (Block Transfer)
08 SERCOS interface
09 CANBUS
C 0d Wireless controller
diff --git a/hwdb/pnp_id_registry.html b/hwdb/pnp_id_registry.html
index a2752e252e..11a6f9ff6d 100644
--- a/hwdb/pnp_id_registry.html
+++ b/hwdb/pnp_id_registry.html
@@ -2423,6 +2423,17 @@
<tr class="odd"><td>VRgineers, Inc.</td><td>VRG</td><td>09/07/2017</td> </tr>
<tr class="even"><td>Noritake Itron Corporation</td><td>NRI</td><td>11/13/2017</td> </tr>
<tr class="odd"><td>Matrix Orbital Corporation</td><td>MOC</td><td>11/13/2017</td> </tr>
+ <tr class="even"><td>Elegant Invention</td><td>EIN</td><td>03/29/2018</td> </tr>
+ <tr class="odd"><td>Immersive Audio Technologies France</td><td>IMF</td><td>03/29/2018</td> </tr>
+ <tr class="even"><td>Lightspace Technologies</td><td>LSP</td><td>03/29/2018</td> </tr>
+ <tr class="odd"><td>PixelNext Inc</td><td>PXN</td><td>03/29/2018</td> </tr>
+ <tr class="even"><td>VRSHOW Technology Limited</td><td>TSW</td><td>03/29/2018</td> </tr>
+ <tr class="odd"><td>SONOVE GmbH</td><td>SNV</td><td>03/29/2018</td> </tr>
+ <tr class="even"><td>Silex Inside</td><td>SXI</td><td>03/29/2018</td> </tr>
+ <tr class="odd"><td>Huawei Technologies Co., Inc. </td><td>HWV</td><td>04/25/2018</td> </tr>
+ <tr class="even"><td>Varjo Technologies</td><td>VRT</td><td>11/17/2017</td> </tr>
+ <tr class="odd"><td>Japan E.M.Solutions Co., Ltd.</td><td>JEM</td><td>05/24/2018</td> </tr>
+ <tr class="even"><td>QD Laser, Inc.</td><td>QDL</td><td>05/31/2018</td> </tr>
</tbody>
</table>
</body>
diff --git a/hwdb/usb.ids b/hwdb/usb.ids
index cc8556a420..a1db7c6d59 100644
--- a/hwdb/usb.ids
+++ b/hwdb/usb.ids
@@ -9,8 +9,8 @@
# The latest version can be obtained from
# http://www.linux-usb.org/usb.ids
#
-# Version: 2018.01.04
-# Date: 2018-01-04 20:34:07
+# Version: 2018.05.04
+# Date: 2018-05-04 20:34:07
#
# Vendors, devices and interfaces. Please keep sorted.
@@ -29,9 +29,17 @@
7788 counterfeit flash drive
0053 Planex
5301 GW-US54ZGL 802.11bg
+0078 Microntek
+ 0006 Joystick
0079 DragonRise Inc.
0006 PC TWIN SHOCK Gamepad
0011 Gamepad
+ 1800 Mayflash Wii U Pro Game Controller Adapter [DirectInput]
+ 181b Venom Arcade Joystick
+ 1843 Mayflash GameCube Controller Adapter
+ 1844 Mayflash GameCube Controller
+0085 Boeye Technology Co., Ltd.
+ 0600 eBook Reader
0105 Trust International B.V.
145f NW-3100 802.11b/g 54Mbps Wireless Network Adapter [zd1211]
0127 IBP
@@ -50,6 +58,7 @@
0301 MIDI Port
02ad HUMAX Co., Ltd.
138c PVR Mass Storage
+0303 Mini Automation Controller
0324 OCZ Technology Inc
bc06 OCZ ATV USB 2.0 Flash Drive
bc08 OCZ Rally2/ATV USB 2.0 Flash Drive
@@ -174,7 +183,7 @@
6902 Floppy Disk Drive
7500 CD-R/RW
ffff Dongle with BlueCore in DFU mode
-03f0 Hewlett-Packard
+03f0 HP, Inc
0004 DeskJet 895c
0011 OfficeJet G55
0012 DeskJet 1125C Printer Port
@@ -423,6 +432,7 @@
2a1d Integrated Module with Bluetooth 2.1 Wireless technology
2b11 PSC 2170 series
2b17 LaserJet 1020
+ 2b4a Business Slim Keyboard
2c12 Officejet J4680
2c17 LaserJet 1022
2c24 Logitech M-UAL-96 Mouse
@@ -476,10 +486,12 @@
3a02 PhotoSmart 7150
3a11 OfficeJet 5500 series
3a17 Printing Support
+ 3a1d hs2340 HSPA+ mobile broadband
3b02 PhotoSmart 7150~
3b05 Scanjet N8460
3b11 PSC 1300 series
3b17 LaserJet M1005 MFP
+ 3b2a Color LaserJet MFP M277dw
3c02 PhotoSmart 7350
3c05 Scanjet Professional 1000 Mobile Scanner
3c11 PSC 1358
@@ -789,8 +801,12 @@
a951 HCP HIT GSM/GPRS modem [Cinterion MC55i]
a9a0 FT2232D - Dual UART/FIFO IC - FTDI
abb8 Lego Mindstorms NXTCam
+ b0c0 microSensys RFID device
+ b0c1 microSensys RFID device
b0c2 iID contactless RFID device
b0c3 iID contactless RFID device
+ b0c4 RFID device
+ b0c5 RFID device
b810 US Interface Navigator (CAT and 2nd PTT lines)
b811 US Interface Navigator (WKEY and FSK lines)
b812 US Interface Navigator (RS232 and CONFIG lines)
@@ -1126,7 +1142,7 @@
0a68 Func MS-3 gaming mouse [WT6573F MCU]
2367 Human Interface Device [HP CalcPad 200 Calculator and Numeric Keypad]
6510 Weltrend Bar Code Reader
- 6520 XBOX Xploder
+ 6520 Xploder Xbox Memory Unit (8MB)
6533 Speed-Link Competition Pro
6543 Manhattan Magnetic Card Strip Reader
040c VTech Computers, Ltd
@@ -1590,15 +1606,19 @@
2602 USB 2.0 Hub
2640 USB 2.0 Hub
2660 Hub
+ 274d HTC Hub Controller
+ 3fcc RME MADIface
4041 Hub and media card controller
4060 Ultra Fast Media Reader
4064 Ultra Fast Media Reader
5434 Hub
5534 Hub
7500 LAN7500 Ethernet 10/100/1000 Adapter
+ 9500 LAN9500/LAN9500i
9512 SMC9512/9514 USB Hub
9514 SMC9514 Hub
9904 LAN9512/LAN9514 Ethernet 10/100 Adapter (SAL10)
+ 9e00 LAN9500A/LAN9500Ai
a700 2 Port Hub
ec00 SMSC9512/9514 Fast Ethernet Adapter
0425 Motorola Semiconductors HK, Ltd
@@ -1859,6 +1879,11 @@
0402 HOTAS Warthog Joystick
0404 HOTAS Warthog Throttle
044f GP XID
+ 0f00 Steering Wheel for Xbox
+ 0f03 Steering Wheel for Xbox
+ 0f07 Controller for Xbox
+ 0f0c Xbox Memory Unit (8MB)
+ 0f10 Modena GT Wheel
a003 Rage 3D Game Pad
a01b PK-GP301 Driving Wheel
a0a0 Top Gun Joystick
@@ -1876,6 +1901,7 @@
b315 Firestorm Dual Analog 3
b323 Dual Trigger 3-in-1 (PC Mode)
b324 Dual Trigger 3-in-1 (PS3 Mode)
+ b326 Gamepad GP XID
b603 force feedback Wheel
b605 force feedback Racing Wheel
b651 Ferrari GT Rumble Force Wheel
@@ -1897,6 +1923,8 @@
3410 TUSB3410 Microcontroller
3f00 OMAP1610
3f02 SMC WSKP100 Wi-Fi Phone
+ 505f TUSB5052 Serial
+ 5153 TUSB5052 Hub
5409 Frontier Labs NEX IA+ Digital Audio Player
6000 AU5 ADSL Modem (pre-reenum)
6001 AU5 ADSL Modem
@@ -1937,6 +1965,7 @@
0162 SiS162 usb Wireless LAN Adapter
0163 SiS163U 802.11 Wireless LAN Adapter
0817 SiS-184-ASUS-4352.17 touch panel
+ 10e1 HID Touch Controller
5401 Wireless Adapter RO80211GS-USB
0458 KYE Systems Corp. (Mouse Systems)
0001 Mouse
@@ -2177,15 +2206,17 @@
02ae Xbox NUI Camera
02b0 Xbox NUI Motor
02b6 Xbox360 Bluetooth Wireless Headset
+ 02bb Kinect Audio
02be Kinect for Windows NUI Audio
02bf Kinect for Windows NUI Camera
02c2 Kinect for Windows NUI Motor
02d1 Xbox One Controller
02d5 Xbox One Digital TV Tuner
- 02dd Xbox One Controller (Covert Forces/Firmware 2015)
+ 02dd Xbox One Controller (Firmware 2015)
02e3 Xbox One Elite Controller
02e6 Wireless XBox Controller Dongle
02ea Xbox One S Controller
+ 02fd Xbox One S Controller [Bluetooth]
0400 Windows Powered Pocket PC 2002
0401 Windows Powered Pocket PC 2002
0402 Windows Powered Pocket PC 2002
@@ -2352,9 +2383,20 @@
0799 Surface Pro embedded keyboard
07a5 Wireless Receiver 1461C
07b9 Wired Keyboard 200
+ 07c6 RTL8153 GigE [Surface Dock Ethernet]
07ca Surface Pro 3 Docking Station Audio Device
+ 07cd Surface Keyboard
07f8 Wired Keyboard 600 (model 1576)
07fd Nano Transceiver 1.1
+ 0900 Surface Dock Hub
+ 0901 Surface Dock Hub
+ 0902 Surface Dock Hub
+ 0903 Surface Dock Hub
+ 0904 Surface Dock Extender
+ 0905 Surface Dock Audio
+ 090b Hub
+ 090c SD Card
+ 091a Hub
0a00 Lumia 950 Dual SIM (RM-1118)
930a ISOUSB.SYS Intel 82930 Isochronous IO Test Board
ffca Catalina
@@ -2422,6 +2464,7 @@
4d62 HP Laser Mobile Mini Mouse
4d75 Rocketfish RF-FLBTAD Bluetooth Adapter
4d81 Dell N889 Optical Mouse
+ 4de3 HP 5-Button Optical Comfort Mouse
4de7 webcam
4e04 Lenovo Keyboard KB1021
0463 MGE UPS Systems
@@ -2439,7 +2482,7 @@
0010 SmartBoard XX44
0011 G83 (RS 6000) Keyboard
0021 CyMotion Expert Combo
- 0023 CyMotion Master Linux Keyboard G230
+ 0023 Keyboard
0027 CyMotion Master Solar Keyboard
002a Wireless Mouse & Keyboard
002d SmartTerminal XX44
@@ -2449,6 +2492,7 @@
0041 G86 6240 Keyboard
0080 eHealth Terminal ST 1503
0081 eHealth Keyboard G87 1504
+ 00a1 SmartCard Reader Keyboard KC 1000 SC
0106 R-300 Wireless Mouse Receiver
010d MX-Board 3.0 Keyboard
b090 Keyboard
@@ -2464,6 +2508,7 @@
0082 Acer Aspire 5672 Webcam
0200 WingMan Extreme Joystick
0203 M2452 Keyboard
+ 0242 Chillstream for Xbox 360
0301 M4848 Mouse
0401 HP PageScan
0402 NEC PageScan
@@ -2484,6 +2529,7 @@
081d HD Webcam C510
0820 QuickCam VC
0821 HD Webcam C910
+ 0823 HD Webcam B910
0825 Webcam C270
0826 HD Webcam C525
0828 HD Webcam B990
@@ -2709,9 +2755,9 @@
c213 J-UH16 (Freedom 2.4 Cordless Joystick)
c214 ATK3 (Attack III Joystick)
c215 Extreme 3D Pro
- c216 Dual Action Gamepad
- c218 Logitech RumblePad 2 USB
- c219 Cordless RumblePad 2
+ c216 F310 Gamepad [DirectInput Mode]
+ c218 F510 Gamepad [DirectInput Mode]
+ c219 F710 Gamepad [DirectInput Mode]
c21a Precision Gamepad
c21c G13 Advanced Gameboard
c21d F310 Gamepad [XInput Mode]
@@ -2853,8 +2899,13 @@
c720 Bluetooth wireless hub
ca03 MOMO Racing
ca04 Formula Vibration Feedback Wheel
+ ca84 Cordless Controller for Xbox
+ ca88 Thunderpad for Xbox
+ ca8a Precision Vibration Feedback Wheel for Xbox
+ caa3 DriveFX Racing Wheel
cab1 Cordless Keyboard for Wii HID Receiver
d001 QuickCam Pro
+ f301 Controller
046e Behavior Tech. Computer Corp.
0100 Keyboard
3001 Mass Storage Device
@@ -2972,6 +3023,7 @@
20e3 GoGear Raga
20e4 GoGear ViBE 8GB
2160 Mio LINK Heart Rate Monitor
+ 21e0 GoGEAR Raga
262c SPC230NC Webcam
485d Senselock SenseIV v2.x
df55 LPCXpresso LPC-Link
@@ -3142,6 +3194,7 @@
0203 AH-K3001V
0204 iBurst Terminal
0408 FS-1320D Printer
+ 0640 ECOSYS M6026cdn
069b ECOSYS M2635dn
0483 STMicroelectronics
0137 BeWAN ADSL USB ST (blue or green)
@@ -3162,13 +3215,18 @@
5000 ST Micro/Ergenic ERG BT-002 Bluetooth Adapter
5001 ST Micro Bluetooth Device
5710 Joystick in FS Mode
- 5720 STM microSD Flash Device
+ 5720 Mass Storage Device
5721 Hantek DDS-3X25 Arbitrary Waveform Generator
- 5730 STM32 Audio Streaming
- 5740 STM32F407
+ 5722 Bulk Demo
+ 5730 Audio Speaker
+ 5731 Microphone
+ 5740 Virtual COM Port
7270 ST Micro Serial Bridge
7554 56k SoftModem
+ 8213 ThermaData Logger Cradle
+ 8259 Probe
91d1 Sensor Hub
+ a171 ThermaData WiFi
df11 STM Device in DFU Mode
ff10 Swann ST56 Modem
0484 Specialix
@@ -3192,6 +3250,7 @@
e032 Broadcom BCM20702 Bluetooth
e042 Broadcom BCM20702 Bluetooth
e04d Atheros AR3012 Bluetooth
+ e055 BCM43142A0 broadcom bluetooth
048a S-MOS Systems, Inc.
048c Alps Electric Ireland, Ltd
048d Integrated Technology Express, Inc.
@@ -3460,6 +3519,7 @@
049b Strobe XP 100
04a0 7400
04ac Xerox Travel Scanner 100
+ 04bb strobe 400 scanner
04cd Xerox Travel Scanner 150
04a8 Multivideo Labs, Inc.
0101 Hub
@@ -3548,6 +3608,7 @@
1607 DR-6080 Scanner
1608 DR-2580C Scanner
1609 DR-3080CII
+ 160a DR-2050C Scanner
1700 PIXMA MP110 Scanner
1701 PIXMA MP130 Scanner
1702 MP410 Composite
@@ -3711,11 +3772,14 @@
2623 FAX-B180C
2629 FAXPHONE L75
262b LaserShot LBP-1120 Printer
+ 262c imageCLASS D300
262d iR C3200
262f PIXMA MP730
2630 PIXMA MP700
2631 LASER CLASS 700
2632 FAX-L2000
+ 2633 LASERCLASS 500
+ 2634 PC-D300/FAX-L400/ICD300
2635 MPC190
2637 iR C6800
2638 iR C3100
@@ -3770,6 +3834,7 @@
2687 iR4530
2688 LBP3460
2689 FAX-L180/L380S/L398S
+ 268a LC310/L390/L408S
268c iR C6870
268d iR 6870C EUR
268e iR C5870
@@ -3958,6 +4023,7 @@
3193 PowerShot SD990 IS DIGITAL ELPH / Digital IXUS 980 IS / IXY DIGITAL 3000 IS
3195 PowerShot SX1 IS
3196 PowerShot SD880 IS DIGITAL ELPH / Digital IXUS 870 IS / IXY DIGITAL 920 IS
+ 3199 EOS 5D Mark II
319a EOS 7D
319b EOS 50D
31aa SELPHY CP770
@@ -4098,6 +4164,7 @@
32c1 PowerShot ELPH 180 / IXUS 175
32c2 PowerShot SX720 HS
32d5 PowerShot SX430 IS
+ 32db SELPHY CP1300
04aa DaeWoo Telecom, Ltd
04ab Chromatic Research
04ac Micro Audiometrics Corp.
@@ -4240,6 +4307,9 @@
5500 HID->COM RS232 Adapter
5a9b Dacal CD/DVD Library D-101/DC-300/DC-016RW
6370 ViewMate Desktop Mouse CC2201
+ 6502 CY4609
+ 6506 CY4603
+ 650a CY4613
6560 CY7C65640 USB-2.0 "TetraHub"
6830 CY7C68300A EZ-USB AT2 USB 2.0 to ATA/ATAPI
6831 Storage Adapter ISD-300LP (CY)
@@ -4257,6 +4327,7 @@
f000 CY30700 Licorice evaluation board
f111 CY8CKIT-002 PSoC MiniProg3 Rev A Program and debug kit
f115 PSoC FirstTouch Programmer
+ f231 DELLY Changer 4in1 universal IR remote
f232 Mono embedded computer
fd13 Programmable power socket
04b5 ROHM LSI Systems USA, LLC
@@ -4581,6 +4652,7 @@
300d Atheros AR3012 Bluetooth
300f Atheros AR3012 Bluetooth
3014 Qualcomm Atheros Bluetooth
+ 7022 HP HD Webcam
7025 HP HD Webcam
7046 TOSHIBA Web Camera - HD
9304 Hub
@@ -4593,7 +4665,7 @@
0109 FinePix F601 Zoom (PC CAM)
010a FinePix S602 (Pro) Zoom (DSC)
010b FinePix S602 (Pro) Zoom (PC CAM)
- 010d FinePix Digital Camera 020531
+ 010d FinePix S2 pro
010e FinePix F402 Zoom (DSC)
010f FinePix F402 Zoom (PC CAM)
0110 FinePix M603 Zoom (DSC)
@@ -4735,6 +4807,7 @@
8108 ChipKit Pro MX7 (PIC32MX)
9004 Microchip REAL ICE
900a PICkit3
+ 9012 PICkit4
c001 PicoLCD 20x4
e11c TL866CS EEPROM Programmer [MiniPRO]
f2c4 Macareux-labs Hygrometry Temperature Sensor
@@ -4775,6 +4848,7 @@
2834 HT82A834R Audio MCU
a01c wireless multimedia keyboard with trackball [Trust ADURA 17911]
a050 Chatman V1
+ a052 USB-zyTemp
a055 Keyboard
a096 Keyboard
a09f E-Signal LUOM G10 Mechanical Gaming Mouse
@@ -5010,6 +5084,7 @@
3268 ML-1610 Mono Laser Printer
326c ML-2010P Mono Laser Printer
3276 ML-3050/ML-3051 Laser Printer
+ 327e ML-2510 Series
328e CLP-310 Color Laser Printer
3292 ML-1640 Series Laser Printer
3296 ML-2580N Mono Laser Printer
@@ -5119,6 +5194,7 @@
61b5 M3 Portable Hard Drive 2TB
61b6 M3 Portable Hard Drive 1TB
61f3 Portable SSD T3 (MU-PT250B, MU-PT500B)
+ 61f5 Portable SSD T5
6601 Mobile Phone
6602 Galaxy
6603 Galaxy
@@ -5219,6 +5295,7 @@
0618 RG-0618U Wireless HID Receiver & KG-0609 Wireless Keyboard with Touchpad
0718 wired mouse
0760 Acer KU-0760 Keyboard
+ 0833 KU-0833 Keyboard
0841 HP Multimedia Keyboard
0860 2.4G Multimedia Wireless Kit
1061 HP KG-1061 Wireless Keyboard+Mouse
@@ -5271,6 +5348,7 @@
b15c Sony Vaio Integrated Camera
b175 4-Port Hub
b1aa Webcam-101
+ b1ac HP Laptop Integrated Webcam [2 MP Fixed]
b1b4 Lenovo Integrated Camera
b1b9 Asus Integrated Webcam
b1cf Lenovo Integrated Camera
@@ -5287,7 +5365,9 @@
b2b0 Camera
b2b9 Lenovo Integrated Camera UVC
b2da thinkpad t430s camera
+ b2db Thinkpad T430 camera
b2ea Integrated Camera [ThinkPad]
+ b2f4 HP Webcam-50
b330 Asus 720p CMOS webcam
b354 UVC 1.00 device HD UVC WebCam
b394 Integrated Camera
@@ -5296,6 +5376,8 @@
b3fd HD WebCam (Asus N-series)
b40e HP Truevision HD camera
b444 Lenovo Integrated Webcam
+ b5ce Integrated Camera
+ b5cf Integrated IR Camera
04f3 Elan Microelectronics Corp.
000a Touchscreen
0103 ActiveJet K-2024 Multimedia Keyboard
@@ -5308,6 +5390,7 @@
0230 3D Optical Mouse
0232 Mouse
0234 Optical Mouse
+ 0235 Optical Mouse
02f4 2.4G Cordless Mouse
0381 Touchscreen
04a0 Dream Cheeky Stress/Panic Button
@@ -6071,7 +6154,7 @@
a4a2 Linux-USB Ethernet/RNDIS Gadget
a4a3 Linux-USB user-mode isochronous source/sink
a4a4 Linux-USB user-mode bulk source/sink
- a4a5 Pocketbook Pro 903
+ a4a5 Pocketbook Pro 903 / Mobius 2 Action Cam
a4a6 Linux-USB Serial Gadget
a4a7 Linux-USB Serial Gadget (CDC ACM mode)
a4a8 Linux-USB Printer Gadget
@@ -6217,7 +6300,7 @@
054c Sony Corp.
0001 HUB
0002 Standard HUB
- 0010 DSC-S30/S70/S75/F505V/F505/FD92/W1 Cybershot/Mavica Digital Camera
+ 0010 Cyber-shot, Mavica (msc)
0014 Nogatech USBVision (SY)
0022 Storage Adapter V2 (TPP)
0023 CD Writer
@@ -6394,17 +6477,19 @@
0485 MHS-PM5 HD camcorder
04cb WALKMAN NWZ-E354
0541 DSC-HX100V [Cybershot Digital Still Camera]
- 05c4 DualShock 4 [CUH-ZCT1E]
+ 05c4 DualShock 4 [CUH-ZCT1x]
0689 Walkman NWZ-B173F
06bb WALKMAN NWZ-F805
06c3 RC-S380
07c4 ILCE-6000 (aka Alpha-6000) in Mass Storage mode
+ 082f Walkman NWZW Series
0847 WG-C10 Portable Wireless Server
088c Portable Headphone Amplifier
08b7 ILCE-6000 (aka Alpha-6000) in MTP mode
094e ILCE-6000 (aka Alpha-6000) in PC Remote mode
0994 ILCE-6000 (aka Alpha-6000) in charging mode
- 09cc DualShock 4 [CUH-ZCT2E]
+ 09cc DualShock 4 [CUH-ZCT2x]
+ 0ba0 Dualshock4 Wireless Adaptor
0bb5 Headset MDR-1000X
1000 Wireless Buzz! Receiver
054d Try Corp.
@@ -6510,6 +6595,7 @@
0408 BearPaw 2448 CU Pro
0409 BearPaw 2448 TA Pro
040b ScanExpress A3 USB 1200 PRO
+ 0501 ScanExpress A3 2400 Pro
0873 ScanExpress 600 USB
1000 BearPaw 4800 TA Pro
a350 gSmart 350 Camera
@@ -6702,12 +6788,30 @@
034e DTH-W1620 [MobileStudio Pro 16] tablet
034f DTH-1320 [Cintiq Pro 13] tablet
0350 DTH-1620 [Cintiq Pro 16] tablet
+ 0351 DTH-2420 [Cintiq Pro 24 PT] tablet
+ 0352 DTH-3220 [Cintiq Pro 32] tablet
0353 DTH-1320 [Cintiq Pro 13] touchscreen
0354 DTH-1620 [Cintiq Pro 16] touchscreen
+ 0355 DTH-2420 [Cintiq Pro 24 PT] touchscreen
+ 0356 DTH-3220 [Cintiq Pro 32] touchscreen
0357 PTH-660 [Intuos Pro (M)]
0358 PTH-860 [Intuos Pro (L)]
035a DTH-1152 tablet
0368 DTH-1152 touchscreen
+ 0374 CTL-4100 [Intuos (S)]
+ 0375 CTL-6100 [Intuos (M)]
+ 0376 CTL-4100WL [Intuos BT (S)]
+ 0378 CTL-6100WL [Intuos BT (M)]
+ 037a CTL-472 [One by Wacom (S)]
+ 037b CTL-672 [One by Wacom (M)]
+ 037c DTK-2420 [Cintiq Pro 24 P]
+ 037d DTH-2452 tablet
+ 037e DTH-2452 touchscreen
+ 0382 DTK-2451 tablet
+ 038a DTH-3220 [Cintiq Pro 32] internal hub
+ 038d DTH-3220 [Cintiq Pro 32] internal hub
+ 038e DTH-3220 [Cintiq Pro 32] external hub
+ 038f DTH-3220 [Cintiq Pro 32] internal hub
0400 PenPartner 4x5
4001 TPC4001
4004 TPC4004
@@ -6729,7 +6833,16 @@
056e Elecom Co., Ltd
0002 29UO Mouse
0057 M-PGDL Mouse
- 0072 Mouse
+ 005c M-PGDL Mouse
+ 005d M-FGDL Mouse
+ 005e M-FG2DL Mouse
+ 0062 M-D18DR Mouse
+ 0063 M-SODL Mouse
+ 0069 M-GE1UL Mouse
+ 0071 M-GE3DL Mouse
+ 0072 M-LS6UL Mouse
+ 0073 M-LS7UL Mouse
+ 0074 M-FW1UL Mouse
200c LD-USB/TX
4002 Laneed 100Mbps Ethernet LD-USB/TX [pegasus]
4005 LD-USBL/TX
@@ -18468,10 +18581,11 @@
20f4 TRENDnet
648b TEW-648UBM 802.11n 150Mbps Micro Wireless N Adapter [Realtek RTL8188CUS]
20f7 XIMEA
- 3001 Camera with CMOS sensor [MQ]
- 3021 Camera with CCD sensor [MD]
- 30b3 Camera with CMOS sensor in Vision mode [MQ]
- a003 Subminiature 5Mpix B/W Camera, MU9PM-MH
+ 3001 MQ or MD camera
+ 3002 MU camera
+ 3021 MJ camera
+ 30b3 MQ in U3V mode or MC camera
+ a003 MU camera
2100 RT Systems
9e52 Yaesu VX-7
9e54 CT29B Radio Cable
@@ -18686,6 +18800,18 @@
0044 Mega ADK R3 (CDC ACM)
0045 Serial R3 (CDC ACM)
8036 Leonardo (CDC ACM, HID)
+2357 TP-Link
+ 0100 TL-WN8200ND [Realtek RTL8192CU]
+ 0101 RTL8812AU Archer T4U 802.11ac
+ 0103 Archer T4UH wireless Realtek 8812AU
+ 0105 Archer T1U 802.11a/n/ac Wireless Adapter [MediaTek MT7610U]
+ 0107 TL-WN821N Version 5 RTL8192EU
+ 0108 TL-WN822N Version 4 RTL8192EU
+ 0109 TL WN823N RTL8192EU
+ 010c TL-WN722N v2
+ 010e TL-WN722N v2
+ 0200 MA 180 Zero CD
+ 0201 HSUPA Modem MA180
2373 Pumatronix Ltda
0001 5 MegaPixel Digital Still Camera [DSC5M]
2375 Digit@lway, Inc.
@@ -18878,6 +19004,14 @@
14ea GW-US11H WLAN
2c1a Dolphin Peripherals
0000 Wireless Optical Mouse
+2c7c Quectel Wireless Solutions Co., Ltd.
+ 0121 EC21 LTE modem
+ 0125 EC25 LTE modem
+ 0191 EG91 LTE modem
+ 0195 EG95 LTE modem
+ 0296 BG96 CAT-M1/NB-IoT modem
+ 0306 EG06/EP06/EM06 LTE-A modem
+ 0435 AG35 LTE modem
2dcf Dialog Semiconductor
c952 Audio Class 2.0 Devices
2fb2 Fujitsu, Ltd
diff --git a/man/.dir-locals.el b/man/.dir-locals.el
new file mode 100644
index 0000000000..1c2512052d
--- /dev/null
+++ b/man/.dir-locals.el
@@ -0,0 +1,14 @@
+; special .c mode with reduced indentation for man pages
+((nil . ((indent-tabs-mode . nil)
+ (tab-width . 8)
+ (fill-column . 79)))
+ (c-mode . ((fill-column . 80)
+ (c-basic-offset . 2)
+ (eval . (c-set-offset 'substatement-open 0))
+ (eval . (c-set-offset 'statement-case-open 0))
+ (eval . (c-set-offset 'case-label 0))
+ (eval . (c-set-offset 'arglist-intro '++))
+ (eval . (c-set-offset 'arglist-close 0))))
+ (nxml-mode . ((nxml-child-indent . 2)
+ (fill-column . 119)))
+ (meson-mode . ((meson-indent-basic . 8))))
diff --git a/man/binfmt.d.xml b/man/binfmt.d.xml
index 4b085bcc16..a4e508251c 100644
--- a/man/binfmt.d.xml
+++ b/man/binfmt.d.xml
@@ -3,23 +3,6 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="binfmt.d" conditional='ENABLE_BINFMT'
xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -27,15 +10,6 @@
<refentryinfo>
<title>binfmt.d</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -67,11 +41,9 @@
<refsect1>
<title>Configuration Format</title>
- <para>Each file contains a list of binfmt_misc kernel binary
- format rules. Consult <ulink
- url="https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst">binfmt-misc.rst</ulink>
- for more information on registration of additional binary formats
- and how to write rules.</para>
+ <para>Each file contains a list of binfmt_misc kernel binary format rules. Consult the kernel's <ulink
+ url="https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html">binfmt-misc.rst</ulink> documentation
+ file for more information on registration of additional binary formats and how to write rules.</para>
<para>Empty lines and lines beginning with ; and # are ignored.
Note that this means you may not use ; and # as delimiter in
diff --git a/man/bootctl.xml b/man/bootctl.xml
index 7662593a70..9521dc9d98 100644
--- a/man/bootctl.xml
+++ b/man/bootctl.xml
@@ -4,21 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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="bootctl" conditional='ENABLE_EFI'
@@ -26,15 +11,6 @@
<refentryinfo>
<title>bootctl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -49,51 +25,19 @@
<refsynopsisdiv>
<cmdsynopsis>
- <command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> status</command>
- </cmdsynopsis>
- <cmdsynopsis>
- <command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> list</command>
- </cmdsynopsis>
- <cmdsynopsis>
- <command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> update</command>
- </cmdsynopsis>
- <cmdsynopsis>
- <command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> install</command>
- </cmdsynopsis>
- <cmdsynopsis>
- <command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> remove</command>
+ <command>bootctl</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para><command>bootctl</command> checks, updates,
- installs or removes the boot loader from the current
- system.</para>
-
- <para><command>bootctl status</command> checks and prints the
- currently installed versions of the boot loader binaries and
- all current EFI boot variables.</para>
-
- <para><command>bootctl list</command> displays all configured boot loader entries.
- </para>
-
- <para><command>bootctl update</command> updates all installed versions of systemd-boot, if the current version is
- newer than the version installed in the EFI system partition. This also includes the EFI default/fallback loader at
- <filename>/EFI/BOOT/BOOT*.EFI</filename>. A systemd-boot entry in the EFI boot variables is created if there is no
- current entry. The created entry will be added to the end of the boot order list.</para>
-
- <para><command>bootctl install</command> installs systemd-boot into the EFI system partition. A copy of
- systemd-boot will be stored as the EFI default/fallback loader at <filename>/EFI/BOOT/BOOT*.EFI</filename>. A
- systemd-boot entry in the EFI boot variables is created and added to the top of the boot order list.</para>
-
- <para><command>bootctl remove</command> removes all installed
- versions of systemd-boot from the EFI system partition, and removes
- systemd-boot from the EFI boot variables.</para>
-
- <para>If no command is passed, <command>status</command> is
- implied.</para>
+ <para><command>bootctl</command> can check the EFI boot loader status, list
+ available entries, and install, update, or remove the
+ <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ boot loader on the current system.</para>
</refsect1>
<refsect1>
@@ -126,16 +70,64 @@
</refsect1>
<refsect1>
+ <title>Commands</title>
+ <variablelist>
+
+ <varlistentry>
+ <term><option>status</option></term>
+
+ <listitem><para>Shows the currently installed versions of the boot loader binaries and all current
+ EFI boot variables. If no command is specified, this is the implied default.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>list</option></term>
+
+ <listitem><para>Shows all configured boot loader entries.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>update</option></term>
+
+ <listitem><para>Updates all installed versions of
+ <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ if the current version is newer than the version installed in the EFI system
+ partition. This also includes the EFI default/fallback loader at
+ <filename><replaceable>ESP</replaceable>/EFI/BOOT/BOOT*.EFI</filename>. A
+ systemd-boot entry in the EFI boot variables is created if there is no current
+ entry. The created entry will be added to the end of the boot order list.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>install</option></term>
+
+ <listitem><para>Installs systemd-boot into the EFI system partition. A copy of systemd-boot will
+ be stored as the EFI default/fallback loader at
+ <filename><replaceable>ESP</replaceable>/EFI/BOOT/BOOT*.EFI</filename>. A systemd-boot entry in
+ the EFI boot variables is created and added to the top of the boot order list.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>remove</option></term>
+
+ <listitem><para>Removes all installed versions of systemd-boot from the EFI system partition,
+ and removes systemd-boot from the EFI boot variables.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
<title>Exit status</title>
- <para>On success, 0 is returned, a non-zero failure
- code otherwise.</para>
+ <para>On success, 0 is returned, a non-zero failure code otherwise.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
- <ulink url="https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec">Boot loader specification</ulink>
- <ulink url="https://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface">systemd boot loader interface</ulink>
+ <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <ulink url="https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md">Boot Loader Specification</ulink>,
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface">Boot Loader Interface</ulink>
</para>
</refsect1>
</refentry>
diff --git a/man/bootup.xml b/man/bootup.xml
index 56f4f57097..5f63fe7784 100644
--- a/man/bootup.xml
+++ b/man/bootup.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="bootup">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>bootup</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -112,6 +86,8 @@
other units. Units near the top are started before units nearer to
the bottom of the chart.</para>
+ <!-- note: do not use unicode ellipsis here, because docbook will replace that
+ with three dots anyway, messing up alignment -->
<programlisting>local-fs-pre.target
|
v
@@ -296,8 +272,18 @@ systemd-reboot.service systemd-poweroff.service systemd-halt.service syste
v v v v
<emphasis>reboot.target</emphasis> <emphasis>poweroff.target</emphasis> <emphasis>halt.target</emphasis> <emphasis>kexec.target</emphasis></programlisting>
- <para>Commonly used system shutdown targets are
- <emphasis>emphasized</emphasis>.</para>
+ <para>Commonly used system shutdown targets are <emphasis>emphasized</emphasis>.</para>
+
+ <para>Note that
+ <citerefentry><refentrytitle>systemd-halt.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <filename>systemd-reboot.service</filename>, <filename>systemd-poweroff.service</filename> and
+ <filename>systemd-kexec.service</filename> will transition the system and server manager (PID 1) into the second
+ phase of system shutdown (implemented in the <filename>systemd-shutdown</filename> binary), which will unmount any
+ remaining file systems, kill any remaining processes and release any other remaining resources, in a simple and
+ robust fashion, without taking any service or unit concept into account anymore. At that point, regular
+ applications and resources are generally terminated and released already, the second phase hence operates only as
+ safety net for everything that couldn't be stopped or released for some reason during the primary, unit-based
+ shutdown phase described above.</para>
</refsect1>
<refsect1>
@@ -307,6 +293,7 @@ systemd-reboot.service systemd-poweroff.service systemd-halt.service syste
<citerefentry project='man-pages'><refentrytitle>boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-halt.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry project='die-net'><refentrytitle>dracut</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/busctl.xml b/man/busctl.xml
index 2320cb8ed3..c0bbed1c87 100644
--- a/man/busctl.xml
+++ b/man/busctl.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="busctl"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>busctl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/coredump.conf.xml b/man/coredump.conf.xml
index f6ac86aaf5..43a3679130 100644
--- a/man/coredump.conf.xml
+++ b/man/coredump.conf.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="coredump.conf" conditional="ENABLE_COREDUMP"
@@ -28,15 +11,6 @@
<refentryinfo>
<title>coredump.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -87,7 +61,7 @@
<listitem><para>Controls where to store cores. One of <literal>none</literal>,
<literal>external</literal>, and <literal>journal</literal>. When
- <literal>none</literal>, the core dumps will be logged (including the backtrace if
+ <literal>none</literal>, the core dumps may be logged (including the backtrace if
possible), but not stored permanently. When <literal>external</literal> (the
default), cores will be stored in <filename>/var/lib/systemd/coredump/</filename>.
When <literal>journal</literal>, cores will be stored in the journal and rotated
@@ -114,8 +88,12 @@
<listitem><para>The maximum size in bytes of a core
which will be processed. Core dumps exceeding this size
- will be logged, but the backtrace will not be generated
- and the core will not be stored.</para></listitem>
+ may be stored, but the backtrace will not be generated.
+ </para>
+
+ <para>Setting <varname>Storage=none</varname> and <varname>ProcessSizeMax=0</varname>
+ disables all coredump handling except for a log entry.</para>
+ </listitem>
</varlistentry>
<varlistentry>
diff --git a/man/coredumpctl.xml b/man/coredumpctl.xml
index 72191d1dc2..caa1bb1c0f 100644
--- a/man/coredumpctl.xml
+++ b/man/coredumpctl.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="coredumpctl" conditional='ENABLE_COREDUMP'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>coredumpctl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -133,6 +107,15 @@
</varlistentry>
<varlistentry>
+ <term><option>--debugger=</option><replaceable>DEBUGGER</replaceable></term>
+
+ <listitem><para>Use the given debugger for the <command>debug</command>
+ command. If not given and <varname>$SYSTEMD_DEBUGGER</varname> is unset, then
+ <citerefentry><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ will be used. </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-D</option> <replaceable>DIR</replaceable></term>
<term><option>--directory=</option><replaceable>DIR</replaceable></term>
@@ -241,10 +224,14 @@
</varlistentry>
<varlistentry>
- <term><command>gdb</command></term>
-
- <listitem><para>Invoke the GNU debugger on the last core dump
- matching specified characteristics. </para></listitem>
+ <term><command>debug</command></term>
+
+ <listitem><para>Invoke a debugger on the last core dump
+ matching specified characteristics. By default,
+ <citerefentry><refentrytitle>gdb</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ will be used. This may be changed using the <option>--debugger=</option>
+ option or the <varname>$SYSTEMD_DEBUGGER</varname> environment
+ variable.</para></listitem>
</varlistentry>
</variablelist>
@@ -284,9 +271,10 @@
<varlistentry>
<term><replaceable>MATCH</replaceable></term>
- <listitem><para>General journalctl predicate (see
- <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>).
- Must contain an equals sign (<literal>=</literal>).</para></listitem>
+ <listitem><para>General journalctl match filter, must contain an equals
+ sign (<literal>=</literal>). See
+ <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ </para></listitem>
</varlistentry>
</variablelist>
</refsect1>
@@ -300,6 +288,18 @@
</refsect1>
<refsect1>
+ <title>Environment</title>
+
+ <variablelist class='environment-variables'>
+ <varlistentry>
+ <term><varname>$SYSTEMD_DEBUGGER</varname></term>
+ <listitem><para>Use the given debugger for the <command>debug</command>
+ command. See the <option>--debugger=</option> option.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
<title>Examples</title>
<example>
@@ -311,7 +311,7 @@
<example>
<title>Invoke gdb on the last core dump</title>
- <programlisting># coredumpctl gdb</programlisting>
+ <programlisting># coredumpctl debug</programlisting>
</example>
<example>
diff --git a/man/crypttab.xml b/man/crypttab.xml
index dc43257d4e..dcaf03d2ca 100644
--- a/man/crypttab.xml
+++ b/man/crypttab.xml
@@ -4,49 +4,16 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
This is based on crypttab(5) from Fedora's initscripts package, which in
turn is based on Debian's version.
The Red Hat version has been written by Miloslav Trmac <mitr@redhat.com>.
-
-->
<refentry id="crypttab" conditional='HAVE_LIBCRYPTSETUP'>
<refentryinfo>
<title>crypttab</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Documentation</contrib>
- <firstname>Miloslav</firstname>
- <surname>Trmac</surname>
- <email>mitr@redhat.com</email>
- </author>
- <author>
- <contrib>Documentation</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/custom-entities.ent.in b/man/custom-entities.ent.in
index a1dbf7133f..e2bd44e5e7 100644
--- a/man/custom-entities.ent.in
+++ b/man/custom-entities.ent.in
@@ -6,4 +6,5 @@
<!ENTITY systemenvgeneratordir @SYSTEM_ENV_GENERATOR_PATH@>
<!ENTITY userenvgeneratordir @USER_ENV_GENERATOR_PATH@>
<!ENTITY CERTIFICATE_ROOT @CERTIFICATE_ROOT@>
-<!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_ON_OFF@>
+<!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
+<!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
diff --git a/man/custom-html.xsl b/man/custom-html.xsl
index e8a7404df3..fccaf51ff5 100644
--- a/man/custom-html.xsl
+++ b/man/custom-html.xsl
@@ -3,22 +3,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
diff --git a/man/custom-man.xsl b/man/custom-man.xsl
index 3307fd3c0d..d9af519d32 100644
--- a/man/custom-man.xsl
+++ b/man/custom-man.xsl
@@ -2,23 +2,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
diff --git a/man/daemon.xml b/man/daemon.xml
index ab65f6f4d9..730507ed7e 100644
--- a/man/daemon.xml
+++ b/man/daemon.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="daemon">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>daemon</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/dnssec-trust-anchors.d.xml b/man/dnssec-trust-anchors.d.xml
index d6e488065b..541febc38b 100644
--- a/man/dnssec-trust-anchors.d.xml
+++ b/man/dnssec-trust-anchors.d.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="dnssec-trust-anchors.d" conditional='ENABLE_RESOLVE'
@@ -28,15 +11,6 @@
<refentryinfo>
<title>dnssec-trust-anchors.d</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/environment.d.xml b/man/environment.d.xml
index 7dedfa4891..2257dcb04c 100644
--- a/man/environment.d.xml
+++ b/man/environment.d.xml
@@ -4,23 +4,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2016 Red Hat, Inc.
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Red Hat, Inc.
-->
<refentry id="environment.d" conditional='ENABLE_ENVIRONMENT_D'
xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +12,6 @@
<refentryinfo>
<title>environment.d</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Ray</firstname>
- <surname>Strode</surname>
- <email>rstrode@redhat.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/file-hierarchy.xml b/man/file-hierarchy.xml
index f14b9aa250..23ee17d36f 100644
--- a/man/file-hierarchy.xml
+++ b/man/file-hierarchy.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="file-hierarchy">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>file-hierarchy</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -84,7 +58,7 @@
</varlistentry>
<varlistentry>
- <term><filename>/boot</filename></term>
+ <term><filename>/boot/</filename></term>
<listitem><para>The boot partition used for bringing up the
system. On EFI systems, this is possibly the EFI System
Partition (ESP), also see
@@ -106,7 +80,7 @@
</varlistentry>
<varlistentry>
- <term><filename>/etc</filename></term>
+ <term><filename>/etc/</filename></term>
<listitem><para>System-specific configuration. This directory
may or may not be read-only. Frequently, this directory is
pre-populated with vendor-supplied configuration files, but
@@ -117,7 +91,7 @@
</varlistentry>
<varlistentry>
- <term><filename>/home</filename></term>
+ <term><filename>/home/</filename></term>
<listitem><para>The location for normal user's home
directories. Possibly shared with other systems, and never
read-only. This directory should only be used for normal
@@ -134,16 +108,16 @@
</varlistentry>
<varlistentry>
- <term><filename>/root</filename></term>
+ <term><filename>/root/</filename></term>
<listitem><para>The home directory of the root user. The root
user's home directory is located outside of
- <filename>/home</filename> in order to make sure the root user
- may log in even without <filename>/home</filename> being
+ <filename>/home/</filename> in order to make sure the root user
+ may log in even without <filename>/home/</filename> being
available and mounted.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/srv</filename></term>
+ <term><filename>/srv/</filename></term>
<listitem><para>The place to store general server payload,
managed by the administrator. No restrictions are made how
this directory is organized internally. Generally writable,
@@ -153,11 +127,11 @@
</varlistentry>
<varlistentry>
- <term><filename>/tmp</filename></term>
+ <term><filename>/tmp/</filename></term>
<listitem><para>The place for small temporary files. This
directory is usually mounted as a <literal>tmpfs</literal>
instance, and should hence not be used for larger files. (Use
- <filename>/var/tmp</filename> for larger files.) Since the
+ <filename>/var/tmp/</filename> for larger files.) Since the
directory is accessible to other users of the system, it is
essential that this directory is only written to with the
<citerefentry project='man-pages'><refentrytitle>mkstemp</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
@@ -167,7 +141,7 @@
time are usually automatically deleted. If applications find
the environment variable <varname>$TMPDIR</varname> set, they
should prefer using the directory specified in it over
- directly referencing <filename>/tmp</filename> (see
+ directly referencing <filename>/tmp/</filename> (see
<citerefentry project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>
and
<ulink url="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03">IEEE
@@ -182,7 +156,7 @@
<variablelist>
<varlistentry>
- <term><filename>/run</filename></term>
+ <term><filename>/run/</filename></term>
<listitem><para>A <literal>tmpfs</literal> file system for
system packages to place runtime data in. This directory is
flushed on boot, and generally writable for privileged
@@ -190,15 +164,15 @@
</varlistentry>
<varlistentry>
- <term><filename>/run/log</filename></term>
+ <term><filename>/run/log/</filename></term>
<listitem><para>Runtime system logs. System components may
place private logs in this directory. Always writable, even
- when <filename>/var/log</filename> might not be accessible
+ when <filename>/var/log/</filename> might not be accessible
yet.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/run/user</filename></term>
+ <term><filename>/run/user/</filename></term>
<listitem><para>Contains per-user runtime directories, each
usually individually mounted <literal>tmpfs</literal>
instances. Always writable, flushed at each reboot and when
@@ -218,7 +192,7 @@
<variablelist>
<varlistentry>
- <term><filename>/usr</filename></term>
+ <term><filename>/usr/</filename></term>
<listitem><para>Vendor-supplied operating system resources.
Usually read-only, but this is not required. Possibly shared
between multiple hosts. This directory should not be modified
@@ -227,23 +201,23 @@
</varlistentry>
<varlistentry>
- <term><filename>/usr/bin</filename></term>
+ <term><filename>/usr/bin/</filename></term>
<listitem><para>Binaries and executables for user commands
that shall appear in the <varname>$PATH</varname> search path.
It is recommended not to place binaries in this directory that
are not useful for invocation from a shell (such as daemon
binaries); these should be placed in a subdirectory of
- <filename>/usr/lib</filename> instead.</para></listitem>
+ <filename>/usr/lib/</filename> instead.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/usr/include</filename></term>
+ <term><filename>/usr/include/</filename></term>
<listitem><para>C and C++ API header files of system
libraries.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/usr/lib</filename></term>
+ <term><filename>/usr/lib/</filename></term>
<listitem><para>Static, private vendor data that is compatible
with all architectures (though not necessarily
architecture-independent). Note that this includes internal
@@ -255,15 +229,15 @@
</varlistentry>
<varlistentry>
- <term><filename>/usr/lib/<replaceable>arch-id</replaceable></filename></term>
+ <term><filename>/usr/lib/<replaceable>arch-id</replaceable>/</filename></term>
<listitem><para>Location for placing dynamic libraries into, also
called <varname>$libdir</varname>. The architecture identifier
to use is defined on <ulink
url="https://wiki.debian.org/Multiarch/Tuples">Multiarch
Architecture Specifiers (Tuples)</ulink> list. Legacy
locations of <varname>$libdir</varname> are
- <filename>/usr/lib</filename>,
- <filename>/usr/lib64</filename>. This directory should not be
+ <filename>/usr/lib/</filename>,
+ <filename>/usr/lib64/</filename>. This directory should not be
used for package-specific data, unless this data is
architecture-dependent, too. To query
<varname>$libdir</varname> for the primary architecture of the
@@ -273,7 +247,7 @@
</varlistentry>
<varlistentry>
- <term><filename>/usr/share</filename></term>
+ <term><filename>/usr/share/</filename></term>
<listitem><para>Resources shared between multiple packages,
such as documentation, man pages, time zone information, fonts
and other resources. Usually, the precise location and format
@@ -282,29 +256,29 @@
</varlistentry>
<varlistentry>
- <term><filename>/usr/share/doc</filename></term>
+ <term><filename>/usr/share/doc/</filename></term>
<listitem><para>Documentation for the operating system or
system packages.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/usr/share/factory/etc</filename></term>
+ <term><filename>/usr/share/factory/etc/</filename></term>
<listitem><para>Repository for vendor-supplied default
configuration files. This directory should be populated with
pristine vendor versions of all configuration files that may
- be placed in <filename>/etc</filename>. This is useful to
+ be placed in <filename>/etc/</filename>. This is useful to
compare the local configuration of a system with vendor
defaults and to populate the local configuration with
defaults.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/usr/share/factory/var</filename></term>
+ <term><filename>/usr/share/factory/var/</filename></term>
<listitem><para>Similar to
- <filename>/usr/share/factory/etc</filename>, but for vendor
+ <filename>/usr/share/factory/etc/</filename>, but for vendor
versions of files in the variable, persistent data directory
- <filename>/var</filename>.</para></listitem>
+ <filename>/var/</filename>.</para></listitem>
</varlistentry>
</variablelist>
@@ -315,7 +289,7 @@
<variablelist>
<varlistentry>
- <term><filename>/var</filename></term>
+ <term><filename>/var/</filename></term>
<listitem><para>Persistent, variable system data. Must be
writable. This directory might be pre-populated with
vendor-supplied data, but applications should be able to
@@ -330,7 +304,7 @@
</varlistentry>
<varlistentry>
- <term><filename>/var/cache</filename></term>
+ <term><filename>/var/cache/</filename></term>
<listitem><para>Persistent system cache data. System
components may place non-essential data in this directory.
Flushing this directory should have no effect on operation of
@@ -339,13 +313,13 @@
</varlistentry>
<varlistentry>
- <term><filename>/var/lib</filename></term>
+ <term><filename>/var/lib/</filename></term>
<listitem><para>Persistent system data. System components may
place private data in this directory.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/var/log</filename></term>
+ <term><filename>/var/log/</filename></term>
<listitem><para>Persistent system logs. System components may
place private logs in this directory, though it is recommended
to do most logging via the
@@ -356,21 +330,21 @@
</varlistentry>
<varlistentry>
- <term><filename>/var/spool</filename></term>
+ <term><filename>/var/spool/</filename></term>
<listitem><para>Persistent system spool data, such as printer
or mail queues.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/var/tmp</filename></term>
+ <term><filename>/var/tmp/</filename></term>
<listitem><para>The place for larger and persistent temporary
- files. In contrast to <filename>/tmp</filename>, this directory
+ files. In contrast to <filename>/tmp/</filename>, this directory
is usually mounted from a persistent physical file system and
- can thus accept larger files. (Use <filename>/tmp</filename>
+ can thus accept larger files. (Use <filename>/tmp/</filename>
for smaller files.) This directory is generally not flushed at
boot-up, but time-based cleanup of files that have not been
accessed for a certain time is applied. The same security
- restrictions as with <filename>/tmp</filename> apply, and
+ restrictions as with <filename>/tmp/</filename> apply, and
hence only
<citerefentry project='man-pages'><refentrytitle>mkstemp</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>mkdtemp</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@@ -378,7 +352,7 @@
If applications find the environment variable
<varname>$TMPDIR</varname> set, they should prefer using the
directory specified in it over directly referencing
- <filename>/var/tmp</filename> (see
+ <filename>/var/tmp/</filename> (see
<citerefentry project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details). </para></listitem>
</varlistentry>
@@ -391,7 +365,7 @@
<variablelist>
<varlistentry>
- <term><filename>/dev</filename></term>
+ <term><filename>/dev/</filename></term>
<listitem><para>The root directory for device nodes. Usually,
this directory is mounted as a <literal>devtmpfs</literal>
instance, but might be of a different type in
@@ -404,7 +378,7 @@
</varlistentry>
<varlistentry>
- <term><filename>/dev/shm</filename></term>
+ <term><filename>/dev/shm/</filename></term>
<listitem><para>Place for POSIX shared memory segments, as
created via
<citerefentry project='die-net'><refentrytitle>shm_open</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
@@ -414,7 +388,7 @@
to avoid name clashes and vulnerabilities. For normal users,
shared memory segments in this directory are usually deleted
when the user logs out. Usually, it is a better idea to use
- memory mapped files in <filename>/run</filename> (for system
+ memory mapped files in <filename>/run/</filename> (for system
programs) or <varname>$XDG_RUNTIME_DIR</varname> (for user
programs) instead of POSIX shared memory segments, since these
directories are not world-writable and hence not vulnerable to
@@ -422,7 +396,7 @@
</varlistentry>
<varlistentry>
- <term><filename>/proc</filename></term>
+ <term><filename>/proc/</filename></term>
<listitem><para>A virtual kernel file system exposing the
process list and other functionality. This file system is
mostly an API to interface with the kernel and not a place
@@ -433,8 +407,8 @@
</varlistentry>
<varlistentry>
- <term><filename>/proc/sys</filename></term>
- <listitem><para>A hierarchy below <filename>/proc</filename>
+ <term><filename>/proc/sys/</filename></term>
+ <listitem><para>A hierarchy below <filename>/proc/</filename>
that exposes a number of kernel tunables. The primary way to
configure the settings in this API file tree is via
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
@@ -443,7 +417,7 @@
</varlistentry>
<varlistentry>
- <term><filename>/sys</filename></term>
+ <term><filename>/sys/</filename></term>
<listitem><para>A virtual kernel file system exposing
discovered devices and other functionality. This file system
is mostly an API to interface with the kernel and not a place
@@ -461,27 +435,27 @@
<variablelist>
<varlistentry>
- <term><filename>/bin</filename></term>
- <term><filename>/sbin</filename></term>
- <term><filename>/usr/sbin</filename></term>
+ <term><filename>/bin/</filename></term>
+ <term><filename>/sbin/</filename></term>
+ <term><filename>/usr/sbin/</filename></term>
<listitem><para>These compatibility symlinks point to
- <filename>/usr/bin</filename>, ensuring that scripts and
+ <filename>/usr/bin/</filename>, ensuring that scripts and
binaries referencing these legacy paths correctly find their
binaries.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/lib</filename></term>
+ <term><filename>/lib/</filename></term>
<listitem><para>This compatibility symlink points to
- <filename>/usr/lib</filename>, ensuring that programs
+ <filename>/usr/lib/</filename>, ensuring that programs
referencing this legacy path correctly find their
resources.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>/lib64</filename></term>
+ <term><filename>/lib64/</filename></term>
<listitem><para>On some architecture ABIs, this compatibility
symlink points to <varname>$libdir</varname>, ensuring that
@@ -492,10 +466,10 @@
</varlistentry>
<varlistentry>
- <term><filename>/var/run</filename></term>
+ <term><filename>/var/run/</filename></term>
<listitem><para>This compatibility symlink points to
- <filename>/run</filename>, ensuring that programs referencing
+ <filename>/run/</filename>, ensuring that programs referencing
this legacy path correctly find their runtime
data.</para></listitem>
</varlistentry>
@@ -517,7 +491,7 @@
<variablelist>
<varlistentry>
- <term><filename>~/.cache</filename></term>
+ <term><filename>~/.cache/</filename></term>
<listitem><para>Persistent user cache data. User programs may
place non-essential data in this directory. Flushing this
@@ -530,7 +504,7 @@
</varlistentry>
<varlistentry>
- <term><filename>~/.config</filename></term>
+ <term><filename>~/.config/</filename></term>
<listitem><para>Application configuration and state. When a
new user is created, this directory will be empty or not exist
@@ -542,13 +516,13 @@
</varlistentry>
<varlistentry>
- <term><filename>~/.local/bin</filename></term>
+ <term><filename>~/.local/bin/</filename></term>
<listitem><para>Executables that shall appear in the user's
<varname>$PATH</varname> search path. It is recommended not to
place executables in this directory that are not useful for
invocation from a shell; these should be placed in a
- subdirectory of <filename>~/.local/lib</filename> instead.
+ subdirectory of <filename>~/.local/lib/</filename> instead.
Care should be taken when placing architecture-dependent
binaries in this place, which might be problematic if the home
directory is shared between multiple hosts with different
@@ -556,14 +530,14 @@
</varlistentry>
<varlistentry>
- <term><filename>~/.local/lib</filename></term>
+ <term><filename>~/.local/lib/</filename></term>
<listitem><para>Static, private vendor data that is compatible
with all architectures.</para></listitem>
</varlistentry>
<varlistentry>
- <term><filename>~/.local/lib/<replaceable>arch-id</replaceable></filename></term>
+ <term><filename>~/.local/lib/<replaceable>arch-id</replaceable>/</filename></term>
<listitem><para>Location for placing public dynamic libraries.
The architecture identifier to use is defined on <ulink
@@ -573,7 +547,7 @@
</varlistentry>
<varlistentry>
- <term><filename>~/.local/share</filename></term>
+ <term><filename>~/.local/share/</filename></term>
<listitem><para>Resources shared between multiple packages,
such as fonts or artwork. Usually, the precise location and
@@ -587,7 +561,6 @@
</variablelist>
</refsect1>
-
<refsect1>
<title>Unprivileged Write Access</title>
@@ -595,21 +568,21 @@
of the hierarchy.</para>
<para>The exceptions for normal users are
- <filename>/tmp</filename>,
- <filename>/var/tmp</filename>,
- <filename>/dev/shm</filename>, as well as the home directory
+ <filename>/tmp/</filename>,
+ <filename>/var/tmp/</filename>,
+ <filename>/dev/shm/</filename>, as well as the home directory
<varname>$HOME</varname> (usually found below
- <filename>/home</filename>) and the runtime directory
+ <filename>/home/</filename>) and the runtime directory
<varname>$XDG_RUNTIME_DIR</varname> (found below
- <filename>/run/user</filename>) of the user, which are all
+ <filename>/run/user/</filename>) of the user, which are all
writable.</para>
<para>For unprivileged system processes, only
- <filename>/tmp</filename>,
- <filename>/var/tmp</filename> and
- <filename>/dev/shm</filename> are writable. If an
+ <filename>/tmp/</filename>,
+ <filename>/var/tmp/</filename> and
+ <filename>/dev/shm/</filename> are writable. If an
unprivileged system process needs a private writable directory in
- <filename>/var</filename> or <filename>/run</filename>, it is
+ <filename>/var/</filename> or <filename>/run/</filename>, it is
recommended to either create it before dropping privileges in the
daemon code, to create it via
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
@@ -627,9 +600,9 @@
including regular files, directories, symlinks, character and
block device nodes, sockets and FIFOs.</para>
- <para>It is strongly recommended that <filename>/dev</filename> is
+ <para>It is strongly recommended that <filename>/dev/</filename> is
the only location below which device nodes shall be placed.
- Similarly, <filename>/run</filename> shall be the only location to
+ Similarly, <filename>/run/</filename> shall be the only location to
place sockets and FIFOs. Regular files, directories and symlinks
may be used in all directories.</para>
</refsect1>
@@ -655,23 +628,23 @@
</thead>
<tbody>
<row>
- <entry><filename>/usr/bin</filename></entry>
+ <entry><filename>/usr/bin/</filename></entry>
<entry>Package executables that shall appear in the <varname>$PATH</varname> executable search path, compiled for any of the supported architectures compatible with the operating system. It is not recommended to place internal binaries or binaries that are not commonly invoked from the shell in this directory, such as daemon binaries. As this directory is shared with most other packages of the system, special care should be taken to pick unique names for files placed here, that are unlikely to clash with other package's files.</entry>
</row>
<row>
- <entry><filename>/usr/lib/<replaceable>arch-id</replaceable></filename></entry>
+ <entry><filename>/usr/lib/<replaceable>arch-id</replaceable>/</filename></entry>
<entry>Public shared libraries of the package. As above, be careful with using too generic names, and pick unique names for your libraries to place here to avoid name clashes.</entry>
</row>
<row>
- <entry><filename>/usr/lib/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/usr/lib/<replaceable>package</replaceable>/</filename></entry>
<entry>Private static vendor resources of the package, including private binaries and libraries, or any other kind of read-only vendor data.</entry>
</row>
<row>
- <entry><filename>/usr/lib/<replaceable>arch-id</replaceable>/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/usr/lib/<replaceable>arch-id</replaceable>/<replaceable>package</replaceable>/</filename></entry>
<entry>Private other vendor resources of the package that are architecture-specific and cannot be shared between architectures. Note that this generally does not include private executables since binaries of a specific architecture may be freely invoked from any other supported system architecture.</entry>
</row>
<row>
- <entry><filename>/usr/include/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/usr/include/<replaceable>package</replaceable>/</filename></entry>
<entry>Public C/C++ APIs of public shared libraries of the package.</entry>
</row>
</tbody>
@@ -679,7 +652,7 @@
</table>
<para>Additional static vendor files may be installed in the
- <filename>/usr/share</filename> hierarchy to the locations
+ <filename>/usr/share/</filename> hierarchy to the locations
defined by the various relevant specifications.</para>
<para>During runtime, and for local configuration and state,
@@ -698,31 +671,31 @@
</thead>
<tbody>
<row>
- <entry><filename>/etc/<replaceable>package</replaceable></filename></entry>
- <entry>System-specific configuration for the package. It is recommended to default to safe fallbacks if this configuration is missing, if this is possible. Alternatively, a <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> fragment may be used to copy or symlink the necessary files and directories from <filename>/usr/share/factory</filename> during boot, via the <literal>L</literal> or <literal>C</literal> directives.</entry>
+ <entry><filename>/etc/<replaceable>package</replaceable>/</filename></entry>
+ <entry>System-specific configuration for the package. It is recommended to default to safe fallbacks if this configuration is missing, if this is possible. Alternatively, a <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> fragment may be used to copy or symlink the necessary files and directories from <filename>/usr/share/factory/</filename> during boot, via the <literal>L</literal> or <literal>C</literal> directives.</entry>
</row>
<row>
- <entry><filename>/run/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/run/<replaceable>package</replaceable>/</filename></entry>
<entry>Runtime data for the package. Packages must be able to create the necessary subdirectories in this tree on their own, since the directory is flushed automatically on boot. Alternatively, a <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> fragment may be used to create the necessary directories during boot, or the <varname>RuntimeDirectory=</varname> directive of service units may be used to create them at service startup (see <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details).</entry>
</row>
<row>
- <entry><filename>/run/log/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/run/log/<replaceable>package</replaceable>/</filename></entry>
<entry>Runtime log data for the package. As above, the package needs to make sure to create this directory if necessary, as it will be flushed on every boot.</entry>
</row>
<row>
- <entry><filename>/var/cache/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/var/cache/<replaceable>package</replaceable>/</filename></entry>
<entry>Persistent cache data of the package. If this directory is flushed, the application should work correctly on next invocation, though possibly slowed down due to the need to rebuild any local cache files. The application must be capable of recreating this directory should it be missing and necessary. To create an empty directory, a <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> fragment or the <varname>CacheDirectory=</varname> directive of service units (see <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>) may be used.</entry>
</row>
<row>
- <entry><filename>/var/lib/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/var/lib/<replaceable>package</replaceable>/</filename></entry>
<entry>Persistent private data of the package. This is the primary place to put persistent data that does not fall into the other categories listed. Packages should be able to create the necessary subdirectories in this tree on their own, since the directory might be missing on boot. To create an empty directory, a <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> fragment or the <varname>StateDirectory=</varname> directive of service units (see <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>) may be used.</entry>
</row>
<row>
- <entry><filename>/var/log/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/var/log/<replaceable>package</replaceable>/</filename></entry>
<entry>Persistent log data of the package. As above, the package should make sure to create this directory if necessary, possibly using <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> or <varname>LogsDirectory=</varname> (see <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>), as it might be missing.</entry>
</row>
<row>
- <entry><filename>/var/spool/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>/var/spool/<replaceable>package</replaceable>/</filename></entry>
<entry>Persistent spool/queue data of the package. As above, the package should make sure to create this directory if necessary, as it might be missing.</entry>
</row>
</tbody>
@@ -754,19 +727,19 @@
</thead>
<tbody>
<row>
- <entry><filename>~/.local/bin</filename></entry>
+ <entry><filename>~/.local/bin/</filename></entry>
<entry>Package executables that shall appear in the <varname>$PATH</varname> executable search path. It is not recommended to place internal executables or executables that are not commonly invoked from the shell in this directory, such as daemon executables. As this directory is shared with most other packages of the user, special care should be taken to pick unique names for files placed here, that are unlikely to clash with other package's files.</entry>
</row>
<row>
- <entry><filename>~/.local/lib/<replaceable>arch-id</replaceable></filename></entry>
+ <entry><filename>~/.local/lib/<replaceable>arch-id</replaceable>/</filename></entry>
<entry>Public shared libraries of the package. As above, be careful with using too generic names, and pick unique names for your libraries to place here to avoid name clashes.</entry>
</row>
<row>
- <entry><filename>~/.local/lib/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>~/.local/lib/<replaceable>package</replaceable>/</filename></entry>
<entry>Private, static vendor resources of the package, compatible with any architecture, or any other kind of read-only vendor data.</entry>
</row>
<row>
- <entry><filename>~/.local/lib/<replaceable>arch-id</replaceable>/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>~/.local/lib/<replaceable>arch-id</replaceable>/<replaceable>package</replaceable>/</filename></entry>
<entry>Private other vendor resources of the package that are architecture-specific and cannot be shared between architectures.</entry>
</row>
</tbody>
@@ -774,7 +747,7 @@
</table>
<para>Additional static vendor files may be installed in the
- <filename>~/.local/share</filename> hierarchy to the locations
+ <filename>~/.local/share/</filename> hierarchy to the locations
defined by the various relevant specifications.</para>
<para>During runtime, and for local configuration and state,
@@ -793,15 +766,15 @@
</thead>
<tbody>
<row>
- <entry><filename>~/.config/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>~/.config/<replaceable>package</replaceable>/</filename></entry>
<entry>User-specific configuration and state for the package. It is required to default to safe fallbacks if this configuration is missing.</entry>
</row>
<row>
- <entry><filename><varname>$XDG_RUNTIME_DIR</varname>/<replaceable>package</replaceable></filename></entry>
+ <entry><filename><varname>$XDG_RUNTIME_DIR</varname>/<replaceable>package</replaceable>/</filename></entry>
<entry>User runtime data for the package.</entry>
</row>
<row>
- <entry><filename>~/.cache/<replaceable>package</replaceable></filename></entry>
+ <entry><filename>~/.cache/<replaceable>package</replaceable>/</filename></entry>
<entry>Persistent cache data of the package. If this directory is flushed, the application should work correctly on next invocation, though possibly slowed down due to the need to rebuild any local cache files. The application must be capable of recreating this directory should it be missing and necessary.</entry>
</row>
</tbody>
diff --git a/man/glib-event-glue.c b/man/glib-event-glue.c
index 32d8e921b8..5201234d85 100644
--- a/man/glib-event-glue.c
+++ b/man/glib-event-glue.c
@@ -1,70 +1,48 @@
-/***
- SPDX-License-Identifier: MIT
-
- Copyright 2014 Tom Gundersen
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-***/
+/* SPDX-License-Identifier: MIT */
#include <stdlib.h>
+#include <glib.h>
+#include <systemd/sd-event.h>
typedef struct SDEventSource {
- GSource source;
- GPollFD pollfd;
- sd_event *event;
+ GSource source;
+ GPollFD pollfd;
+ sd_event *event;
} SDEventSource;
static gboolean event_prepare(GSource *source, gint *timeout_) {
- return sd_event_prepare(((SDEventSource *)source)->event) > 0;
+ return sd_event_prepare(((SDEventSource *)source)->event) > 0;
}
static gboolean event_check(GSource *source) {
- return sd_event_wait(((SDEventSource *)source)->event, 0) > 0;
+ return sd_event_wait(((SDEventSource *)source)->event, 0) > 0;
}
static gboolean event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
- return sd_event_dispatch(((SDEventSource *)source)->event) > 0;
+ return sd_event_dispatch(((SDEventSource *)source)->event) > 0;
}
static void event_finalize(GSource *source) {
- sd_event_unref(((SDEventSource *)source)->event);
+ sd_event_unref(((SDEventSource *)source)->event);
}
static GSourceFuncs event_funcs = {
- .prepare = event_prepare,
- .check = event_check,
- .dispatch = event_dispatch,
- .finalize = event_finalize,
+ .prepare = event_prepare,
+ .check = event_check,
+ .dispatch = event_dispatch,
+ .finalize = event_finalize,
};
GSource *g_sd_event_create_source(sd_event *event) {
- SDEventSource *source;
+ SDEventSource *source;
- source = (SDEventSource *)g_source_new(&event_funcs, sizeof(SDEventSource));
+ source = (SDEventSource *)g_source_new(&event_funcs, sizeof(SDEventSource));
- source->event = sd_event_ref(event);
- source->pollfd.fd = sd_event_get_fd(event);
- source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ source->event = sd_event_ref(event);
+ source->pollfd.fd = sd_event_get_fd(event);
+ source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
- g_source_add_poll((GSource *)source, &source->pollfd);
+ g_source_add_poll((GSource *)source, &source->pollfd);
- return (GSource *)source;
+ return (GSource *)source;
}
diff --git a/man/halt.xml b/man/halt.xml
index 78860d94dd..19857cea84 100644
--- a/man/halt.xml
+++ b/man/halt.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="halt"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>halt</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -166,7 +140,7 @@
<refsect1>
<title>Notes</title>
- <para>These commands are implemented in a way that preserves compatiblity with
+ <para>These commands are implemented in a way that preserves compatibility with
the original SysV commands.
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
verbs <command>halt</command>, <command>poweroff</command>,
diff --git a/man/hostname.xml b/man/hostname.xml
index 7b0fd29237..de33a74785 100644
--- a/man/hostname.xml
+++ b/man/hostname.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="hostname">
<refentryinfo>
<title>hostname</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml
index 9bfead6d21..013f1267ac 100644
--- a/man/hostnamectl.xml
+++ b/man/hostnamectl.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="hostnamectl" conditional='ENABLE_HOSTNAMED'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>hostnamectl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/hwdb.xml b/man/hwdb.xml
index bf89819949..e77776f35f 100644
--- a/man/hwdb.xml
+++ b/man/hwdb.xml
@@ -4,44 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="hwdb" conditional="ENABLE_HWDB">
<refentryinfo>
<title>hwdb</title>
<productname>systemd</productname>
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/inotify-watch-tmp.c b/man/inotify-watch-tmp.c
new file mode 100644
index 0000000000..ca790f0a99
--- /dev/null
+++ b/man/inotify-watch-tmp.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/inotify.h>
+
+#include <systemd/sd-event.h>
+
+#define _cleanup_(f) __attribute__((cleanup(f)))
+
+static int inotify_handler(sd_event_source *source,
+ const struct inotify_event *event,
+ void *userdata) {
+
+ const char *desc = NULL;
+
+ sd_event_source_get_description(source, &desc);
+
+ if (event->mask & IN_Q_OVERFLOW)
+ printf("inotify-handler <%s>: overflow\n", desc);
+ else if (event->mask & IN_CREATE)
+ printf("inotify-handler <%s>: create on %s\n", desc, event->name);
+ else if (event->mask & IN_DELETE)
+ printf("inotify-handler <%s>: delete on %s\n", desc, event->name);
+ else if (event->mask & IN_MOVED_TO)
+ printf("inotify-handler <%s>: moved-to on %s\n", desc, event->name);
+
+ /* Terminate the program if an "exit" file appears */
+ if ((event->mask & (IN_CREATE|IN_MOVED_TO)) &&
+ strcmp(event->name, "exit") == 0)
+ sd_event_exit(sd_event_source_get_event(source), 0);
+
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+ _cleanup_(sd_event_source_unrefp) sd_event_source *source1 = NULL, *source2 = NULL;
+
+ const char *path1 = argc > 1 ? argv[1] : "/tmp";
+ const char *path2 = argc > 2 ? argv[2] : NULL;
+
+ /* Note: failure handling is omitted for brevity */
+
+ sd_event_default(&event);
+
+ sd_event_add_inotify(event, &source1, path1,
+ IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_TO,
+ inotify_handler, NULL);
+ if (path2)
+ sd_event_add_inotify(event, &source2, path2,
+ IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_TO,
+ inotify_handler, NULL);
+
+ sd_event_loop(event);
+
+ return 0;
+}
diff --git a/man/journal-iterate-poll.c b/man/journal-iterate-poll.c
new file mode 100644
index 0000000000..100d07e202
--- /dev/null
+++ b/man/journal-iterate-poll.c
@@ -0,0 +1,25 @@
+#include <poll.h>
+#include <time.h>
+#include <systemd/sd-journal.h>
+
+int wait_for_changes(sd_journal *j) {
+ uint64_t t;
+ int msec;
+ struct pollfd pollfd;
+
+ sd_journal_get_timeout(j, &t);
+ if (t == (uint64_t) -1)
+ msec = -1;
+ else {
+ struct timespec ts;
+ uint64_t n;
+ 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;
+ }
+
+ pollfd.fd = sd_journal_get_fd(j);
+ pollfd.events = sd_journal_get_events(j);
+ poll(&pollfd, 1, msec);
+ return sd_journal_process(j);
+}
diff --git a/man/journal-iterate-wait.c b/man/journal-iterate-wait.c
new file mode 100644
index 0000000000..0a23569f79
--- /dev/null
+++ b/man/journal-iterate-wait.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <string.h>
+#include <systemd/sd-journal.h>
+
+int main(int argc, char *argv[]) {
+ int r;
+ sd_journal *j;
+ r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
+ if (r < 0) {
+ fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
+ return 1;
+ }
+ for (;;) {
+ const void *d;
+ size_t l;
+ r = sd_journal_next(j);
+ if (r < 0) {
+ fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r));
+ break;
+ }
+ if (r == 0) {
+ /* Reached the end, let's wait for changes, and try again */
+ r = sd_journal_wait(j, (uint64_t) -1);
+ if (r < 0) {
+ fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r));
+ break;
+ }
+ continue;
+ }
+ r = sd_journal_get_data(j, "MESSAGE", &d, &l);
+ if (r < 0) {
+ fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
+ continue;
+ }
+ printf("%.*s\n", (int) l, (const char*) d);
+ }
+ sd_journal_close(j);
+ return 0;
+}
diff --git a/man/journal-remote.conf.xml b/man/journal-remote.conf.xml
index ed49c39f35..acc1817cd8 100644
--- a/man/journal-remote.conf.xml
+++ b/man/journal-remote.conf.xml
@@ -5,22 +5,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2015 Chris Morgan
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2015 Chris Morgan
-->
<refentry id="journal-remote.conf" conditional='HAVE_MICROHTTPD'
@@ -28,15 +13,6 @@
<refentryinfo>
<title>journal-remote.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Chris</firstname>
- <surname>Morgan</surname>
- <email>chmorgan@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -61,7 +37,10 @@
<title>Description</title>
<para>These files configure various parameters of
- <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
@@ -80,7 +59,6 @@
</para></listitem>
</varlistentry>
-
<varlistentry>
<term><varname>SplitMode=</varname></term>
@@ -97,7 +75,7 @@
<varlistentry>
<term><varname>ServerCertificateFile=</varname></term>
- <listitem><para>SSL CA certificate in PEM format.</para></listitem>
+ <listitem><para>SSL certificate in PEM format.</para></listitem>
</varlistentry>
<varlistentry>
@@ -113,7 +91,7 @@
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
diff --git a/man/journal-upload.conf.xml b/man/journal-upload.conf.xml
index bbb6df503b..c3bfa47950 100644
--- a/man/journal-upload.conf.xml
+++ b/man/journal-upload.conf.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="journal-upload.conf" conditional='HAVE_MICROHTTPD'
@@ -28,15 +11,6 @@
<refentryinfo>
<title>journal-upload.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Monkey with a keyboard</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -61,7 +35,10 @@
<title>Description</title>
<para>These files configure various parameters of
- <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
@@ -78,7 +55,8 @@
<listitem><para>The URL to upload the journal entries to. See the description
of <varname>--url=</varname> option in
<citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for the description of possible values.</para></listitem>
+ for the description of possible values. There is no default value, so either this
+ option or the command-line option must be always present to make an upload.</para></listitem>
</varlistentry>
<varlistentry>
@@ -106,7 +84,7 @@
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
diff --git a/man/journalctl.xml b/man/journalctl.xml
index 37fb0d67fd..a4f9e2d7ee 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="journalctl"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>journalctl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -382,6 +356,18 @@
not even a timestamp.</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>with-unit</option>
+ </term>
+ <listitem>
+ <para>similar to short-full, but prefixes the unit and
+ user unit names instead of the traditional syslog
+ identifier. Useful when using templated instances, as it
+ will include the arguments in the unit names.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</listitem>
</varlistentry>
@@ -752,7 +738,7 @@
<term><option>--vacuum-time=</option></term>
<term><option>--vacuum-files=</option></term>
- <listitem><para>Removes archived journal files until the disk
+ <listitem><para>Removes the oldest archived journal files until the disk
space they use falls below the specified size (specified with
the usual <literal>K</literal>, <literal>M</literal>,
<literal>G</literal> and <literal>T</literal> suffixes), or all
@@ -930,7 +916,8 @@
<para>With one match specified, all entries with a field matching
the expression are shown:</para>
- <programlisting>journalctl _SYSTEMD_UNIT=avahi-daemon.service</programlisting>
+ <programlisting>journalctl _SYSTEMD_UNIT=avahi-daemon.service
+journalctl _SYSTEMD_CGROUP=/user.slice/user-42.slice/session-c1.scope</programlisting>
<para>If two different fields are matched, only entries matching
both expressions at the same time are shown:</para>
@@ -950,6 +937,19 @@
<programlisting>journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097 + _SYSTEMD_UNIT=dbus.service</programlisting>
+ <para>To show all fields emitted <emphasis>by</emphasis> a unit and <emphasis>about</emphasis>
+ the unit, option <option>-u</option>/<option>--unit=</option> should be used.
+ <command>journalctl -u <replaceable>name</replaceable></command>
+ expands to a complex filter similar to
+ <programlisting>_SYSTEMD_UNIT=<replaceable>name</replaceable>.service
+ + UNIT=<replaceable>name</replaceable>.service _PID=1
+ + OBJECT_SYSTEMD_UNIT=<replaceable>name</replaceable>.service _UID=0
+ + COREDUMP_UNIT=<replaceable>name</replaceable>.service _UID=0 MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1
+ </programlisting>
+ (see <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for an explanation of those patterns).
+ </para>
+
<para>Show all logs generated by the D-Bus executable:</para>
<programlisting>journalctl /usr/bin/dbus-daemon</programlisting>
@@ -975,8 +975,8 @@
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>
diff --git a/man/journald.conf.xml b/man/journald.conf.xml
index 58b21d424b..28324ac102 100644
--- a/man/journald.conf.xml
+++ b/man/journald.conf.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="journald.conf"
@@ -28,15 +11,6 @@
<refentryinfo>
<title>journald.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -60,9 +34,11 @@
<refsect1>
<title>Description</title>
- <para>These files configure various parameters of the systemd
- journal service,
- <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ <para>These files configure various parameters of the systemd journal service,
+ <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
</refsect1>
@@ -107,10 +83,13 @@
<varlistentry>
<term><varname>Compress=</varname></term>
- <listitem><para>Takes a boolean value. If enabled (the
- default), data objects that shall be stored in the journal and
- are larger than a certain threshold are compressed before they
- are written to the file system.</para></listitem>
+ <listitem><para>Can take a boolean value. If enabled (the
+ default), data objects that shall be stored in the journal
+ and are larger than the default threshold of 512 bytes are
+ compressed before they are written to the file system. It
+ can also be set to a number of bytes to specify the
+ compression threshold directly. Suffixes like K, M, and G
+ can be used to specify larger units.</para></listitem>
</varlistentry>
<varlistentry>
@@ -155,7 +134,7 @@
interval is over. A message about the number of dropped
messages is generated. This rate limiting is applied
per-service, so that two services which log do not interfere
- with each other's limits. Defaults to 1000 messages in 30s.
+ with each other's limits. Defaults to 10000 messages in 30s.
The time specification for
<varname>RateLimitIntervalSec=</varname> may be specified in the
following units: <literal>s</literal>, <literal>min</literal>,
@@ -284,7 +263,6 @@
seconds.</para></listitem>
</varlistentry>
-
<varlistentry>
<term><varname>SyncIntervalSec=</varname></term>
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index be55f14e4f..0545f9d84b 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="kernel-command-line">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>kernel-command-line</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/kernel-install.xml b/man/kernel-install.xml
index cc5ca2a2a9..9ead6ea39b 100644
--- a/man/kernel-install.xml
+++ b/man/kernel-install.xml
@@ -5,22 +5,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Harald Hoyer
-->
<refentry id="kernel-install">
@@ -28,15 +13,6 @@
<refentryinfo>
<title>kernel-install</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Harald</firstname>
- <surname>Hoyer</surname>
- <email>harald@redhat.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -191,7 +167,7 @@
<para>
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <ulink url="https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec">Boot loader specification</ulink>
+ <ulink url="https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md">Boot Loader Specification</ulink>
</para>
</refsect1>
diff --git a/man/less-variables.xml b/man/less-variables.xml
index 750815e7ce..a3faa38997 100644
--- a/man/less-variables.xml
+++ b/man/less-variables.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refsect1>
diff --git a/man/libsystemd-pkgconfig.xml b/man/libsystemd-pkgconfig.xml
index b98f60922a..a177fbe463 100644
--- a/man/libsystemd-pkgconfig.xml
+++ b/man/libsystemd-pkgconfig.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refsect1>
diff --git a/man/libudev.xml b/man/libudev.xml
index e92db55759..8cb4ba59fc 100644
--- a/man/libudev.xml
+++ b/man/libudev.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="libudev"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>libudev</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/loader.conf.xml b/man/loader.conf.xml
new file mode 100644
index 0000000000..6f8d0489d2
--- /dev/null
+++ b/man/loader.conf.xml
@@ -0,0 +1,185 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="loader.conf" conditional='ENABLE_EFI'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>loader.conf</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>loader.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>loader.conf</refname>
+ <refpurpose>Configuration file for systemd-boot</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename><replaceable>ESP</replaceable>/loader/loader.conf</filename>,
+ <filename><replaceable>ESP</replaceable>/loader/loader.conf.d/*.conf</filename>
+ </para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ will read <filename>/loader/loader.conf</filename> and any files with the
+ <literal>.conf</literal> extension under
+ <filename>/loader/loader.conf.d/</filename> on the EFI system partition (ESP).
+ </para>
+
+ <para>Each configuration file must consist of an option name, followed by
+ whitespace, and the option value. <literal>#</literal> may be used to start
+ a comment line. Empty and comment lines are ignored.</para>
+
+ <para>Boolean arguments may be written as
+ <literal>yes</literal>/<literal>y</literal>/<literal>true</literal>/<literal>1</literal> or
+ <literal>no</literal>/<literal>n</literal>/<literal>false</literal>/<literal>0</literal>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following configuration options are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>default</term>
+
+ <listitem><para>A glob pattern to select the default entry. The default entry
+ may be changed in the boot menu itself, in which case the name of the
+ selected entry will be stored as an EFI variable, overriding this option.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>timeout</term>
+
+ <listitem><para>How long the boot menu should be shown before the default
+ entry is booted, in seconds. This may be changed in the boot menu itself and
+ will be stored as an EFI variable in that case, overriding this option.
+ </para>
+
+ <para>If the timeout is disabled, the default entry will be booted
+ immediately. The menu can be shown by pressing and holding a key before
+ systemd-boot is launched.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>console-mode</term>
+
+ <listitem><para>This option configures the resolution of the console. Takes a
+ number or one of the special values listed below. The following values may be
+ used:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>0</term>
+ <listitem>
+ <para>Standard UEFI 80x25 mode</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>1</term>
+ <listitem>
+ <para>80x50 mode, not supported by all devices</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>2</term>
+ <listitem>
+ <para>the first non-standard mode provided by the device
+ firmware, if any</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>auto</term>
+ <listitem>
+ <para>Pick a suitable mode automatically using heuristics</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>max</term>
+ <listitem>
+ <para>Pick the highest-numbered available mode</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>keep</term>
+ <listitem>
+ <para>Keep the mode selected by firmware (the default)</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>editor</term>
+
+ <listitem><para>Takes a boolean argument. Enable (the default) or disable the
+ editor. The editor should be disabled if the machine can be accessed by
+ unauthorized persons.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>auto-entries</term>
+
+ <listitem><para>Takes a boolean argument. Enable (the default) or disable
+ entries for other boot entries found on the boot partition. In particular,
+ this may be useful when loader entries are created to show replacement
+ descriptions for those entries.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>auto-firmware</term>
+
+ <listitem><para>Takes a boolean argument. Enable (the default) or disable
+ the "Reboot into firmware" entry.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Example</title>
+
+ <programlisting># /boot/efi/loader/loader.conf
+timeout 0
+default 01234567890abcdef1234567890abdf0-*
+editor no
+ </programlisting>
+
+ <para>The menu will not be shown by default (the menu can still be shown by
+ pressing and holding a key during boot). One of the entries with files with a
+ name starting with <literal>01234567890abcdef1234567890abdf0-</literal> will be
+ selected by default. If more than one entry matches, the one with the highest
+ priority will be selected (generally the one with the highest version number).
+ The editor will be disabled, so it is not possible to alter the kernel command
+ line.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+</refentry>
diff --git a/man/locale.conf.xml b/man/locale.conf.xml
index cd349acdcd..e89d0bead5 100644
--- a/man/locale.conf.xml
+++ b/man/locale.conf.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="locale.conf">
<refentryinfo>
<title>locale.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/localectl.xml b/man/localectl.xml
index eff8bc3c9e..50c7e13257 100644
--- a/man/localectl.xml
+++ b/man/localectl.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="localectl" conditional='ENABLE_LOCALED'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>localectl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -134,11 +108,12 @@
</varlistentry>
<varlistentry>
- <term><command>set-locale LOCALE…</command></term>
+ <term><command>set-locale LOCALE</command></term>
+ <term><command>set-locale VARIABLE=LOCALE…</command></term>
- <listitem><para>Set the system locale. This takes one or more
- assignments such as "LANG=de_DE.utf8",
- "LC_MESSAGES=en_GB.utf8", and so on. See
+ <listitem><para>Set the system locale. This takes one locale such as <literal>en_US.UTF-8</literal>, or takes one or more
+ locale assignments such as <literal>LANG=de_DE.utf8</literal>, <literal>LC_MESSAGES=en_GB.utf8</literal>, and so on. If
+ one locale without variable name is provided, then <literal>LANG=</literal> locale variable will be set. See
<citerefentry project='man-pages'><refentrytitle>locale</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details on the available settings and their meanings. Use
<command>list-locales</command> for a list of available
diff --git a/man/localtime.xml b/man/localtime.xml
index 0341c61614..f51c67f99b 100644
--- a/man/localtime.xml
+++ b/man/localtime.xml
@@ -4,45 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2012 Shawn Landden
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="localtime">
<refentryinfo>
<title>localtime</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- <author>
- <contrib>Developer</contrib>
- <firstname>Shawn</firstname>
- <surname>Landden</surname>
- <email>shawnlandden@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/loginctl.xml b/man/loginctl.xml
index 3863ec6621..67eeffda81 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="loginctl" conditional='ENABLE_LOGIND'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>loginctl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index e9b7118af6..9e88764c6f 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -1,26 +1,12 @@
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
+<!ENTITY % entities SYSTEM "custom-entities.ent" >
+%entities;
+]>
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="logind.conf" conditional='ENABLE_LOGIND'
@@ -28,15 +14,6 @@
<refentryinfo>
<title>logind.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -60,10 +37,10 @@
<refsect1>
<title>Description</title>
- <para>These files configure various parameters of the systemd
- login manager,
- <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
- </para>
+ <para>These files configure various parameters of the systemd login manager,
+ <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>. See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
@@ -126,7 +103,7 @@
corresponding to the session and all processes inside that scope will be
terminated. If false, the scope is "abandoned", see
<citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- and processes are not killed. Defaults to <literal>yes</literal>,
+ and processes are not killed. Defaults to <literal>&KILL_USER_PROCESSES;</literal>,
but see the options <varname>KillOnlyUsers=</varname> and
<varname>KillExcludeUsers=</varname> below.</para>
@@ -175,7 +152,8 @@
<literal>kexec</literal>,
<literal>suspend</literal>,
<literal>hibernate</literal>,
- <literal>hybrid-sleep</literal>, and
+ <literal>hybrid-sleep</literal>,
+ <literal>suspend-then-hibernate</literal>, and
<literal>lock</literal>.
Defaults to <literal>ignore</literal>.</para>
@@ -224,7 +202,8 @@
<literal>kexec</literal>,
<literal>suspend</literal>,
<literal>hibernate</literal>,
- <literal>hybrid-sleep</literal>, and
+ <literal>hybrid-sleep</literal>,
+ <literal>suspend-then-hibernate</literal>, and
<literal>lock</literal>.
If <literal>ignore</literal>, logind will never handle these
keys. If <literal>lock</literal>, all running sessions will be
@@ -334,17 +313,6 @@
</varlistentry>
<varlistentry>
- <term><varname>UserTasksMax=</varname></term>
-
- <listitem><para>Sets the maximum number of OS tasks each user may run concurrently. This controls the
- <varname>TasksMax=</varname> setting of the per-user slice unit, see
- <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details. If assigned the special value <literal>infinity</literal>, no tasks limit is applied.
- Defaults to 33%, which equals 10813 with the kernel's defaults on the host, but might be smaller in
- OS containers.</para></listitem>
- </varlistentry>
-
- <varlistentry>
<term><varname>RemoveIPC=</varname></term>
<listitem><para>Controls whether System V and POSIX IPC objects belonging to the user shall be removed when the
diff --git a/man/machine-id.xml b/man/machine-id.xml
index 3d82a3edaf..7ed2dda436 100644
--- a/man/machine-id.xml
+++ b/man/machine-id.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="machine-id">
<refentryinfo>
<title>machine-id</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -95,7 +69,7 @@
<title>Initialization</title>
<para>Each machine should have a non-empty ID in normal operation. The ID of each
- machine should be unique. To achive those objectives,
+ machine should be unique. To achieve those objectives,
<filename>/etc/machine-id</filename> can be initialized in a few different ways.
</para>
@@ -117,7 +91,7 @@
to be bind-mounted over the real file, in case the image is used read-only.</para>
<para><citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- may be used to to initialize <filename>/etc/machine-id</filename> on mounted (but not
+ may be used to initialize <filename>/etc/machine-id</filename> on mounted (but not
booted) system images.</para>
<para>When a machine is booted with
diff --git a/man/machine-info.xml b/man/machine-info.xml
index b9f4fa821e..476996ce5f 100644
--- a/man/machine-info.xml
+++ b/man/machine-info.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="machine-info">
<refentryinfo>
<title>machine-info</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/machinectl.xml b/man/machinectl.xml
index 93d5299d26..278ca8d677 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="machinectl" conditional='ENABLE_MACHINED'
@@ -29,15 +12,6 @@
<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>
@@ -157,13 +131,6 @@
</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</command>, choose
@@ -212,7 +179,7 @@
<listitem><para>When used with <command>bind</command>, creates the destination file or directory before
applying the bind mount. Note that even though the name of this option suggests that it is suitable only for
- directories, this option also creates the destination file node to mount over if the the object to mount is not
+ directories, this option also creates the destination file node to mount over if the object to mount is not
a directory, but a regular file, device node, socket or FIFO.</para></listitem>
</varlistentry>
@@ -322,6 +289,7 @@
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="no-legend" />
+ <xi:include href="standard-options.xml" xpointer="no-ask-password" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
@@ -1048,6 +1016,7 @@
<refsect1>
<title>See Also</title>
<para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
diff --git a/man/meson.build b/man/meson.build
index 3a684101d2..ec05d73bc6 100644
--- a/man/meson.build
+++ b/man/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
# This is lame, I know, but meson has no other include mechanism
subdir('rules')
diff --git a/man/modules-load.d.xml b/man/modules-load.d.xml
index 0dd0c3c161..57c4c68073 100644
--- a/man/modules-load.d.xml
+++ b/man/modules-load.d.xml
@@ -3,23 +3,6 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="modules-load.d" conditional='HAVE_KMOD'
xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -27,15 +10,6 @@
<refentryinfo>
<title>modules-load.d</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/networkctl.xml b/man/networkctl.xml
index 33e0629d80..8c750cc1b1 100644
--- a/man/networkctl.xml
+++ b/man/networkctl.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 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="networkctl" conditional='ENABLE_NETWORKD'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>networkctl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Documentation</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -158,7 +132,7 @@
<listitem>
<para>Show discovered LLDP (Link Layer Discovery Protocol) neighbors. If one or more link names are specified
only neighbors on those interfaces are shown. Otherwise shows discovered neighbors on all interfaces. Note
- that for this feature to work, <varname>LLDP=</varname> must be turned on on the specific interface, see
+ that for this feature to work, <varname>LLDP=</varname> must be turned on for the specific interface, see
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.</para>
diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml
index 8a16058161..b34ce1d3e0 100644
--- a/man/networkd.conf.xml
+++ b/man/networkd.conf.xml
@@ -5,22 +5,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2014 Vinay Kulkarni
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Vinay Kulkarni
-->
<refentry id="networkd.conf" conditional='ENABLE_NETWORKD'
@@ -28,15 +13,6 @@
<refentryinfo>
<title>networkd.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Vinay</firstname>
- <surname>Kulkarni</surname>
- <email>kulkarniv@vmware.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml
index bf3ea405a1..e1aabacad2 100644
--- a/man/nss-myhostname.xml
+++ b/man/nss-myhostname.xml
@@ -4,24 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
- Copyright 2013 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="nss-myhostname" conditional='ENABLE_MYHOSTNAME'>
@@ -29,15 +11,6 @@
<refentryinfo>
<title>nss-myhostname</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/nss-mymachines.xml b/man/nss-mymachines.xml
index dc3076ab0d..394a905665 100644
--- a/man/nss-mymachines.xml
+++ b/man/nss-mymachines.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="nss-mymachines" conditional='ENABLE_MACHINED'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>nss-mymachines</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/nss-resolve.xml b/man/nss-resolve.xml
index edd4e9d32e..588bc04976 100644
--- a/man/nss-resolve.xml
+++ b/man/nss-resolve.xml
@@ -4,24 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
- Copyright 2013 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="nss-resolve" conditional='ENABLE_RESOLVE'>
@@ -29,15 +11,6 @@
<refentryinfo>
<title>nss-resolve</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml
index 0114a6f936..323f9ab868 100644
--- a/man/nss-systemd.xml
+++ b/man/nss-systemd.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="nss-systemd" conditional='ENABLE_NSS_SYSTEMD'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>nss-systemd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/os-release.xml b/man/os-release.xml
index 59db374411..6cea40cb99 100644
--- a/man/os-release.xml
+++ b/man/os-release.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="os-release">
<refentryinfo>
<title>os-release</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml
index f45631688c..5eab995a52 100644
--- a/man/pam_systemd.xml
+++ b/man/pam_systemd.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="pam_systemd" conditional='HAVE_PAM'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>pam_systemd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -255,8 +229,65 @@
for, if any. (Only applies to seats with a VT available, such
as <literal>seat0</literal>)</para></listitem>
</varlistentry>
+ </variablelist>
+
+ <para>If not set, <command>pam_systemd</command> will determine the
+ values for <varname>$XDG_SEAT</varname> and <varname>$XDG_VTNR</varname>
+ based on the <varname>$DISPLAY</varname> variable.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Session limits</title>
+
+ <para>PAM modules earlier in the stack, that is those that come before <command>pam_systemd.so</command>,
+ can set session scope limits using the PAM context objects. The data for these objects is provided as NUL-terminated C strings
+ and maps directly to the respective unit resource control directives. Note that these limits apply to individual sessions of the user,
+ they do not apply to all user processes as a combined whole. In particular, the per-user <command>user@.service</command> unit instance,
+ which runs the <command>systemd --user</command> manager process and its children, and is tracked outside of any session, being shared
+ by all the user's sessions, is not covered by these limits.
+ </para>
+
+ <para> See
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information about the resources.
+ Also, see <citerefentry><refentrytitle>pam_set_data</refentrytitle><manvolnum>3</manvolnum></citerefentry> for additional information about how to set
+ the context objects.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><varname>systemd.memory_max</varname></term>
+
+ <listitem><para>Sets unit <varname>MemoryMax=</varname>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.tasks_max</varname></term>
+
+ <listitem><para>Sets unit <varname>TasksMax=</varname>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.cpu_weight</varname></term>
+
+ <listitem><para>Sets unit <varname>CPUWeight=</varname>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.io_weight</varname></term>
+ <listitem><para>Sets unit <varname>IOWeight=</varname>.</para></listitem>
+ </varlistentry>
</variablelist>
+
+ <para>Example data as can be provided from an another PAM module:
+ <programlisting>
+pam_set_data(handle, "systemd.memory_max", (void *)"200M", cleanup);
+pam_set_data(handle, "systemd.tasks_max", (void *)"50", cleanup);
+pam_set_data(handle, "systemd.cpu_weight", (void *)"100", cleanup);
+pam_set_data(handle, "systemd.io_weight", (void *)"340", cleanup);
+ </programlisting>
+ </para>
+
</refsect1>
<refsect1>
diff --git a/man/portablectl.xml b/man/portablectl.xml
new file mode 100644
index 0000000000..0926991cbe
--- /dev/null
+++ b/man/portablectl.xml
@@ -0,0 +1,395 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="portablectl" conditional='ENABLE_PORTABLED'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>portablectl</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>portablectl</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>portablectl</refname>
+ <refpurpose>Attach, detach or inspect portable service images</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>portablectl</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>portablectl</command> may be used to attach, detach or inspect portable service images. It's
+ primarily a command interfacing with
+ <citerefentry><refentrytitle>systemd-portabled.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+
+ <para>Portable service images contain an OS file system tree along with
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> unit file
+ information. A service image may be "attached" to the local system. If attached, a set of unit files are copied
+ from the image to the host, and extended with <varname>RootDirectory=</varname> or <varname>RootImage=</varname>
+ assignments (in case of service units) pointing to the image file or directory, ensuring the services will run
+ within the file system context of the image.</para>
+
+ <para>Portable service images are an efficient way to bundle multiple related services and other units together,
+ and transfer them as a whole between systems. When these images are attached the local system the contained units
+ may run in most ways like regular system-provided units, either with full privileges or inside strict sandboxing,
+ depending on the selected configuration.</para>
+
+ <para>Specifically portable service images may be of the following kind:</para>
+
+ <itemizedlist>
+ <listitem><para>Directory trees containing an OS, including the top-level directories <filename>/usr/</filename>,
+ <filename>/etc/</filename>, and so on.</para></listitem>
+
+ <listitem><para>btrfs subvolumes containing OS trees, similar to normal directory trees.</para></listitem>
+
+ <listitem><para>Binary "raw" disk images containing MBR or GPT partition tables and Linux file system
+ partitions.</para></listitem>
+ </itemizedlist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following options are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-q</option></term>
+ <term><option>--quiet</option></term>
+
+ <listitem><para>Suppresses additional informational output while running.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-p</option> <replaceable>PROFILE</replaceable></term>
+ <term><option>--profile=</option><replaceable>PROFILE</replaceable></term>
+
+ <listitem><para>When attaching an image, select the profile to use. By default the <literal>default</literal>
+ profile is used. For details about profiles, see below.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--copy=</option></term>
+
+ <listitem><para>When attaching an image, select whether to prefer copying or symlinking of files installed into
+ the host system. Takes one of <literal>copy</literal> (to prefer copying of files), <literal>symlink</literal>
+ (to prefer creation of symbolic links) or <literal>auto</literal> for an intermediary mode where security
+ profile drop-ins are symlinked while unit files are copied. Note that this option expresses a preference only,
+ in cases where symbolic links cannot be created — for example when the image operated on is a raw disk image,
+ and hence not directly referentiable from the host file system — copying of files is used
+ unconditionally.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--runtime</option></term>
+
+ <listitem><para>When specified the unit and drop-in files are placed in
+ <filename>/run/systemd/system/</filename> instead of <filename>/etc/systemd/system/</filename>. Images attached
+ with this option set hence remain attached only until the next reboot, while they are normally attached
+ persistently.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--no-reload</option></term>
+
+ <listitem><para>Don't reload the service manager after attaching or detaching a portable service
+ image. Normally the service manager is reloaded to ensure it is aware of added or removed unit
+ files.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--cat</option></term>
+
+ <listitem><para>When inspecting portable service images, show the (unprocessed) contents of the metadata files
+ pulled from the image, instead of brief summaries. Specifically, this will show the
+ <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> and unit file
+ contents of the image.</para></listitem>
+ </varlistentry>
+
+ <xi:include href="user-system-options.xml" xpointer="host" />
+ <xi:include href="user-system-options.xml" xpointer="machine" />
+
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
+ <xi:include href="standard-options.xml" xpointer="no-legend" />
+ <xi:include href="standard-options.xml" xpointer="no-ask-password" />
+ <xi:include href="standard-options.xml" xpointer="help" />
+ <xi:include href="standard-options.xml" xpointer="version" />
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Commands</title>
+
+ <para>The following commands are understood:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>list</command></term>
+
+ <listitem><para>List available portable service images. This will list all portable service images discovered
+ in the portable image search paths (see below), along with brief metadata and state information. Note that many
+ of the commands below may both operate on images inside and outside of the search paths. This command is hence
+ mostly a convenience option, the commands are generally not restricted to what this list
+ shows.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>attach</command> <replaceable>IMAGE</replaceable> [<replaceable>PREFIX…</replaceable>]</term>
+
+ <listitem><para>Attach a portable service image to the host system. Expects a file system path to a portable
+ service image file or directory as first argument. If the specified path contains no slash character
+ (<literal>/</literal>) it is understood as image filename that is searched for in the portable service image
+ search paths (see below). To reference a file in the current working directory prefix the filename with
+ <literal>./</literal> to avoid this search path logic.</para>
+
+ <para>When a portable service is attached four operations are executed:</para>
+
+ <orderedlist>
+
+ <listitem><para>All unit files of types <filename>.service</filename>, <filename>.socket</filename>,
+ <filename>.target</filename>, <filename>.timer</filename> and <filename>.path</filename> which match the
+ indicated unit file name prefix are copied from the image to the host's
+ <filename>/etc/systemd/system/</filename> directory (or <filename>/run/systemd/system/</filename> — depending
+ whether <option>--runtime</option> is specified, see above).</para></listitem>
+
+ <listitem><para>For unit files of type <filename>.service</filename> a drop-in is added to these copies that
+ adds <varname>RootDirectory=</varname> or <varname>RootImage=</varname> settings (see
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+ details), that ensures these services are run within the file system of the originating portable service
+ image.</para></listitem>
+
+ <listitem><para>A second drop-in is created: the "profile" drop-in, that may contain additional security
+ settings (and other settings). A number of profiles are available by default but administrators may define
+ their own ones. See below.</para></listitem>
+
+ <listitem><para>If the portable service image file is not already in the search path (see below), a symbolic
+ link to it is created in <filename>/etc/portables/</filename> or
+ <filename>/run/portables/</filename>, to make sure it is included in it.</para></listitem>
+ </orderedlist>
+
+ <para>By default all unit files whose names start with a prefix generated from the image's file name are copied
+ out. Specifically, the prefix is determined from the image file name with any suffix such as
+ <filename>.raw</filename> removed, truncated at the first occurrence of and underscore character
+ (<literal>_</literal>), if there is one. The underscore logic is supposed to be used to versioning so that the
+ an image file <filename>foobar_47.11.raw</filename> will result in a unit file matching prefix of
+ <filename>foobar</filename>. This prefix is then compared with all unit files names contained in the image in
+ the usual directories, but only unit file names where the prefix is followed by <literal>-</literal>,
+ <literal>.</literal> or <literal>@</literal> are considered. Example: if a portable service image file is named
+ <filename>foobar_47.11.raw</filename> then by default all its unit files with names such as
+ <filename>foobar-quux-waldi.service</filename>, <filename>foobar.service</filename> or
+ <filename>foobar@.service</filename> will be considered. It's possible to override the matching prefix: all
+ strings listed on the command line after the image file name are considered prefixes, overriding the implicit
+ logic where the prefix is derived from the image file name.</para>
+
+ <para>By default, after the unit files are attached the service manager's configuration is reloaded, except
+ when <option>--no-reload</option> is specified (see above). This ensures that the new units made available to
+ the service manager are seen by it.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>detach</command> <replaceable>IMAGE</replaceable></term>
+
+ <listitem><para>Detaches a portable service image from the host. This undoes the operations executed by the
+ <command>attach</command> command above, and removes the unit file copies, drop-ins and image symlink
+ again. This command expects an image name or path as parameter. Note that if a path is specified only the last
+ component of it (i.e. the file or directory name itself, not the path to it) is used for finding matching unit
+ files. This is a convencience feature to allow all arguments passed as <command>attach</command> also to
+ <command>detach</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>inspect</command> <replaceable>IMAGE</replaceable> [<replaceable>PREFIX…</replaceable>]</term>
+
+ <listitem><para>Extracts various metadata from a portable service image and presents it to the
+ caller. Specifically, the
+ <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file of the
+ image is retrieved as well as all matching unit files. By default a short summary showing the most relevant
+ metadata in combination with a list of matching unit files is shown (that is the unit files
+ <command>attach</command> would install to the host system). If combined with <option>--cat</option> (see
+ above), the <filename>os-release</filename> data and the units files' contents is displayed unprocessed. This
+ command is useful to determine whether an image qualifies as portable service image, and which unit files are
+ included. This command expects the path to the image as parameter, optionally followed by a list of unit file
+ prefixes to consider, similar to the <command>attach</command> command described above.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>is-attached</command> <replaceable>IMAGE</replaceable></term>
+
+ <listitem><para>Determines whether the specified image is currently attached or not. Unless combined with the
+ <option>--quiet</option> switch this will show a short state identifier for the image. Specifically:</para>
+
+ <table>
+ <title>Image attachment states</title>
+ <tgroup cols='2'>
+ <colspec colname='state'/>
+ <colspec colname='description'/>
+ <thead>
+ <row>
+ <entry>State</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><option>detached</option></entry>
+ <entry>The image is currently not attached.</entry>
+ </row>
+ <row>
+ <entry><option>attached</option></entry>
+ <entry>The image is currently attached, i.e. its unit files have been made available to the host system.</entry>
+ </row>
+ <row>
+ <entry><option>attached-runtime</option></entry>
+ <entry>Like <option>attached</option>, but the unit files have been made available transiently only, i.e. the <command>attach</command> command has been invoked with the <option>--runtime</option> option.</entry>
+ </row>
+ <row>
+ <entry><option>enabled</option></entry>
+ <entry>The image is currently attached, and at least one unit file associated with it has been enabled.</entry>
+ </row>
+ <row>
+ <entry><option>enabled-runtime</option></entry>
+ <entry>Like <option>enabled</option>, but the the unit files have been made available transiently only, i.e. the <command>attach</command> command has been invoked with the <option>--runtime</option> option.</entry>
+ </row>
+ <row>
+ <entry><option>running</option></entry>
+ <entry>The image is currently attached, and at least one unit file associated with it is running.</entry>
+ </row>
+ <row>
+ <entry><option>running-runtime</option></entry>
+ <entry>The image is currently attached transiently, and at least one unit file associated with it is running.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>read-only</command> <replaceable>IMAGE</replaceable> [<replaceable>BOOL</replaceable>]</term>
+
+ <listitem><para>Marks or (unmarks) a portable service image read-only. Takes an image name, followed by a
+ boolean as arguments. If the boolean is omitted, positive is implied, i.e. the image is marked
+ read-only.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>remove</command> <replaceable>IMAGE</replaceable>…</term>
+
+ <listitem><para>Removes one or more portable service images. Note that this command will only remove the
+ specified image path itself — it refers to a symbolic link then the symbolic link is removed and not the
+ image it points to.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>set-limit</command> [<replaceable>IMAGE</replaceable>] <replaceable>BYTES</replaceable></term>
+
+ <listitem><para>Sets the maximum size in bytes that a specific portable service image, or all images, may grow
+ up to on disk (disk quota). Takes either one or two parameters. The first, optional parameter refers to a
+ portable service image name. If specified, the size limit of the specified image is changed. If omitted, the
+ overall size limit of the sum of all images stored locally is changed. The final argument specifies the size
+ limit in bytes, possibly suffixed by the usual K, M, G, T units. If the size limit shall be disabled, specify
+ <literal>-</literal> as size.</para>
+
+ <para>Note that per-image size limits are only supported on btrfs file systems. Also, depending on
+ <varname>BindPaths=</varname> settings in the portable service's unit files directories from the host might be
+ visible in the image environment during runtime which are not affected by this setting, as only the image
+ itself is counted against this limit.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Files and Directories</title>
+
+ <para>Portable service images are preferably stored in <filename>/var/lib/portables/</filename>, but are also
+ searched for in <filename>/etc/portables/</filename>, <filename>/run/systemd/portables/</filename>,
+ <filename>/usr/local/lib/portables/</filename> and <filename>/usr/lib/portables/</filename>. It's recommended not
+ to place image files directly in <filename>/etc/portables/</filename> or
+ <filename>/run/systemd/portables/</filename> (as these are generally not suitable for storing large or non-textual
+ data), but use these directories only for linking images located elsewhere into the image search path.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Profiles</title>
+
+ <para>When portable service images are attached a "profile" drop-in is linked in, which may be used to enforce
+ additional security (and other) restrictions locally. Four profile drop-ins are defined by default, and shipped in
+ <filename>/usr/lib/systemd/portable/profile/</filename>. Additional, local profiles may be defined by placing them
+ in <filename>/etc/systemd/portable/profile/</filename>. The default profiles are:</para>
+
+ <table>
+ <title>Profiles</title>
+ <tgroup cols='2'>
+ <colspec colname='state'/>
+ <colspec colname='description'/>
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><filename>default</filename></entry>
+ <entry>This is the default profile if no other profile name is set via the <option>--profile=</option> (see above). It's fairly restrictive, but should be useful for common, unprivileged system workloads. This includes write access to the logging framework, as well as IPC access to the D-Bus system.</entry>
+ </row>
+ <row>
+ <entry><filename>nonetwork</filename></entry>
+ <entry>Very similar to <filename>default</filename>, but networking is turned off for any services of the portable service image.</entry>
+ </row>
+ <row>
+ <entry><filename>strict</filename></entry>
+ <entry>A profile with very strict settings. This profile excludes IPC (D-Bus) and network access.</entry>
+ </row>
+ <row>
+ <entry><filename>trusted</filename></entry>
+ <entry>A profile with very relaxed settings. In this profile the services run with full privileges.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>For details on this profiles, and their effects please have a look at their precise definitions,
+ e.g. <filename>/usr/lib/systemd/portable/profile/default/service.conf</filename> and similar.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Exit status</title>
+
+ <para>On success, 0 is returned, a non-zero failure code otherwise.</para>
+ </refsect1>
+
+ <xi:include href="less-variables.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-portabled.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd-resolve.xml b/man/resolvectl.xml
index fd5e35954a..ff5b8ad101 100644
--- a/man/systemd-resolve.xml
+++ b/man/resolvectl.xml
@@ -4,142 +4,40 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="systemd-resolve" conditional='ENABLE_RESOLVE'
+<refentry id="resolvectl" conditional='ENABLE_RESOLVE'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
- <title>systemd-resolve</title>
+ <title>resolvectl</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-resolve</refentrytitle>
+ <refentrytitle>resolvectl</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
- <refname>systemd-resolve</refname>
- <refpurpose>Resolve domain names, IPV4 and IPv6 addresses, DNS resource records, and services</refpurpose>
+ <refname>resolvectl</refname>
+ <refname>resolvconf</refname>
+ <refpurpose>Resolve domain names, IPV4 and IPv6 addresses, DNS resource records, and services; introspect and reconfigure the DNS resolver</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <arg choice="plain" rep="repeat"><replaceable>HOSTNAME</replaceable></arg>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <arg choice="plain" rep="repeat"><replaceable>ADDRESS</replaceable></arg>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --type=<replaceable>TYPE</replaceable></command>
- <arg choice="plain" rep="repeat"><replaceable>DOMAIN</replaceable></arg>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --service</command>
- <arg choice="plain"><arg choice="opt"><arg choice="opt"><replaceable>NAME</replaceable></arg>
- <replaceable>TYPE</replaceable></arg> <replaceable>DOMAIN</replaceable></arg>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --openpgp</command>
- <arg choice="plain"><replaceable>USER@DOMAIN</replaceable></arg>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --tlsa</command>
- <arg choice="plain"><replaceable>DOMAIN<optional>:PORT</optional></replaceable></arg>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --statistics</command>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
+ <command>resolvectl</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --reset-statistics</command>
+ <arg choice="req">COMMAND</arg>
+ <arg choice="opt" rep="repeat">NAME</arg>
</cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --flush-caches</command>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --reset-server-features</command>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --status</command>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --set-dns=<replaceable>SERVER</replaceable></command> <command> --set-domain=<replaceable>DOMAIN</replaceable> --set-llmnr=<replaceable>MODE</replaceable> --set-mdns=<replaceable>MODE</replaceable> --set-dnssec=<replaceable>MODE</replaceable> --set-nta=<replaceable>DOMAIN</replaceable></command>
- </cmdsynopsis>
-
- <cmdsynopsis>
- <command>systemd-resolve</command>
- <arg choice="opt" rep="repeat">OPTIONS</arg>
- <command> --revert</command>
- </cmdsynopsis>
-
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para><command>systemd-resolve</command> may be used to resolve domain names, IPv4 and IPv6 addresses, DNS resource
+ <para><command>resolvectl</command> may be used to resolve domain names, IPv4 and IPv6 addresses, DNS resource
records and services with the
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
resolver service. By default, the specified list of parameters will be resolved as hostnames, retrieving their IPv4
@@ -151,36 +49,6 @@
authenticated. All data for which local DNSSEC validation succeeds is considered authenticated. Moreover all data
originating from local, trusted sources is also reported authenticated, including resolution of the local host
name, the <literal>localhost</literal> host name or all data from <filename>/etc/hosts</filename>.</para>
-
- <para>The <option>--type=</option> switch may be used to specify a DNS resource record type (A, AAAA, SOA, MX, …) in
- order to request a specific DNS resource record, instead of the address or reverse address lookups.
- The special value <literal>help</literal> may be used to list known values.</para>
-
- <para>The <option>--service</option> switch may be used to resolve <ulink
- url="https://tools.ietf.org/html/rfc2782">SRV</ulink> and <ulink
- url="https://tools.ietf.org/html/rfc6763">DNS-SD</ulink> services (see below). In this mode, between one and three
- arguments are required. If three parameters are passed the first is assumed to be the DNS-SD service name, the
- second the SRV service type, and the third the domain to search in. In this case a full DNS-SD style SRV and TXT
- lookup is executed. If only two parameters are specified, the first is assumed to be the SRV service type, and the
- second the domain to look in. In this case no TXT RR is requested. Finally, if only one parameter is specified, it
- is assumed to be a domain name, that is already prefixed with an SRV type, and an SRV lookup is done (no
- TXT).</para>
-
- <para>The <option>--openpgp</option> switch may be used to query PGP keys stored as
- <ulink url="https://tools.ietf.org/html/rfc7929">OPENPGPKEY</ulink> resource records.
- When this option is specified one or more e-mail address must be specified.</para>
-
- <para>The <option>--tlsa</option> switch maybe be used to query TLS public
- keys stored as
- <ulink url="https://tools.ietf.org/html/rfc6698">TLSA</ulink> resource records.
- When this option is specified one or more domain names must be specified.</para>
-
- <para>The <option>--statistics</option> switch may be used to show resolver statistics, including information about
- the number of successful and failed DNSSEC validations.</para>
-
- <para>The <option>--reset-statistics</option> may be used to reset various statistics counters maintained the
- resolver, including those shown in the <option>--statistics</option> output. This operation requires root
- privileges.</para>
</refsect1>
<refsect1>
@@ -240,13 +108,6 @@
</varlistentry>
<varlistentry>
- <term><option>--service</option></term>
-
- <listitem><para>Enables service resolution. This enables DNS-SD and simple SRV service resolution, depending
- on the specified list of parameters (see above).</para></listitem>
- </varlistentry>
-
- <varlistentry>
<term><option>--service-address=</option><replaceable>BOOL</replaceable></term>
<listitem><para>Takes a boolean parameter. If true (the default), when doing a service lookup with
@@ -261,28 +122,6 @@
</varlistentry>
<varlistentry>
- <term><option>--openpgp</option></term>
-
- <listitem><para>Enables OPENPGPKEY resource record resolution (see above). Specified e-mail
- addresses are converted to the corresponding DNS domain name, and any OPENPGPKEY keys are
- printed.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>--tlsa</option></term>
-
- <listitem><para>Enables TLSA resource record resolution (see above).
- A query will be performed for each of the specified names prefixed with
- the port and family
- (<literal>_<replaceable>port</replaceable>._<replaceable>family</replaceable>.<replaceable>domain</replaceable></literal>).
- The port number may be specified after a colon
- (<literal>:</literal>), otherwise <constant>443</constant> will be used
- by default. The family may be specified as an argument after
- <option>--tlsa</option>, otherwise <constant>tcp</constant> will be
- used.</para></listitem>
- </varlistentry>
-
- <varlistentry>
<term><option>--cname=</option><replaceable>BOOL</replaceable></term>
<listitem><para>Takes a boolean parameter. If true (the default), DNS CNAME or DNAME redirections are
@@ -315,21 +154,75 @@
query response are shown. Otherwise, this output is suppressed.</para></listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="help" />
+ <xi:include href="standard-options.xml" xpointer="version" />
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Commands</title>
+ <variablelist>
+
+ <varlistentry>
+ <term><option>query <replaceable>HOSTNAME|ADDRESS</replaceable>…</option></term>
+
+ <listitem><para>Resolve domain names, IPv4 and IPv6 addresses.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>service [[<replaceable>NAME</replaceable>] <replaceable>TYPE</replaceable>] <replaceable>DOMAIN</replaceable></option></term>
+
+ <listitem><para>Resolve <ulink url="https://tools.ietf.org/html/rfc6763">DNS-SD</ulink> and
+ <ulink url="https://tools.ietf.org/html/rfc2782">SRV</ulink> services, depending on the specified list of parameters.
+ If three parameters are passed the first is assumed to be the DNS-SD service name, the second the SRV service type,
+ and the third the domain to search in. In this case a full DNS-SD style SRV and TXT lookup is executed. If only two
+ parameters are specified, the first is assumed to be the SRV service type, and the second the domain to look in. In
+ this case no TXT RR is requested. Finally, if only one parameter is specified, it is assumed to be a domain name,
+ that is already prefixed with an SRV type, and an SRV lookup is done (no TXT).</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>openpgp <replaceable>EMAIL@DOMAIN</replaceable>…</option></term>
+
+ <listitem><para>Query PGP keys stored as <ulink url="https://tools.ietf.org/html/rfc7929">OPENPGPKEY</ulink>
+ resource records. Specified e-mail addresses are converted to the corresponding DNS domain name, and any
+ OPENPGPKEY keys are printed.</para></listitem>
+ </varlistentry>
+
<varlistentry>
- <term><option>--statistics</option></term>
+ <term><option>tlsa [<replaceable>FAMILY</replaceable>] <replaceable>DOMAIN</replaceable>[:<replaceable>PORT</replaceable>]…</option></term>
- <listitem><para>If specified general resolver statistics are shown, including information whether DNSSEC is
+ <listitem><para>Query TLS public keys stored as <ulink url="https://tools.ietf.org/html/rfc6698">TLSA</ulink>
+ resource records. A query will be performed for each of the specified names prefixed with the port and family
+ (<literal>_<replaceable>port</replaceable>._<replaceable>family</replaceable>.<replaceable>domain</replaceable></literal>).
+ The port number may be specified after a colon (<literal>:</literal>), otherwise <constant>443</constant> will be used
+ by default. The family may be specified as the first argument, otherwise <constant>tcp</constant> will be used.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>status [<replaceable>LINK</replaceable>…]</option></term>
+
+ <listitem><para>Shows the global and per-link DNS settings in currently in effect. If no command is specified,
+ this is the implied default.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>statistics</option></term>
+
+ <listitem><para>Shows general resolver statistics, including information whether DNSSEC is
enabled and available, as well as resolution and validation statistics.</para></listitem>
</varlistentry>
<varlistentry>
- <term><option>--reset-statistics</option></term>
+ <term><option>reset-statistics</option></term>
- <listitem><para>Resets the statistics counters shown in <option>--statistics</option> to zero.</para></listitem>
+ <listitem><para>Resets the statistics counters shown in <option>statistics</option> to zero.
+ This operation requires root privileges.</para></listitem>
</varlistentry>
<varlistentry>
- <term><option>--flush-caches</option></term>
+ <term><option>flush-caches</option></term>
<listitem><para>Flushes all DNS resource record caches the service maintains locally. This is mostly equivalent
to sending the <constant>SIGUSR2</constant> to the <command>systemd-resolved</command>
@@ -337,7 +230,7 @@
</varlistentry>
<varlistentry>
- <term><option>--reset-server-features</option></term>
+ <term><option>reset-server-features</option></term>
<listitem><para>Flushes all feature level information the resolver learnt about specific servers, and ensures
that the server feature probing logic is started from the beginning with the next look-up request. This is
@@ -346,66 +239,126 @@
</varlistentry>
<varlistentry>
- <term><option>--status</option></term>
-
- <listitem><para>Shows the global and per-link DNS settings in currently in effect.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>--set-dns=SERVER</option></term>
- <term><option>--set-domain=DOMAIN</option></term>
- <term><option>--set-llmnr=MODE</option></term>
- <term><option>--set-mdns=MODE</option></term>
- <term><option>--set-dnssec=MODE</option></term>
- <term><option>--set-nta=DOMAIN</option></term>
-
- <listitem><para>Set per-interface DNS configuration. These switches may be used to configure various DNS
+ <term><option>dns [<replaceable>LINK</replaceable> [<replaceable>SERVER</replaceable>…]]</option></term>
+ <term><option>domain [<replaceable>LINK</replaceable> [<replaceable>DOMAIN</replaceable>…]]</option></term>
+ <term><option>llmnr [<replaceable>LINK</replaceable> [<replaceable>MODE</replaceable>]]</option></term>
+ <term><option>mdns [<replaceable>LINK</replaceable> [<replaceable>MODE</replaceable>]]</option></term>
+ <term><option>dnssec [<replaceable>LINK</replaceable> [<replaceable>MODE</replaceable>]]</option></term>
+ <term><option>dnsovertls [<replaceable>LINK</replaceable> [<replaceable>MODE</replaceable>]]</option></term>
+ <term><option>nta [<replaceable>LINK</replaceable> [<replaceable>DOMAIN</replaceable>…]]</option></term>
+
+ <listitem><para>Get/set per-interface DNS configuration. These commands may be used to configure various DNS
settings for network interfaces that aren't managed by
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>. (These
commands will fail when used on interfaces that are managed by <command>systemd-networkd</command>, please
- configure their DNS settings directly inside the <filename>.network</filename> files instead.) These switches
+ configure their DNS settings directly inside the <filename>.network</filename> files instead.) These commands
may be used to inform <command>systemd-resolved</command> about per-interface DNS configuration determined
- through external means. Multiple of these switches may be passed on a single invocation of
- <command>systemd-resolve</command> in order to set multiple configuration options at once. If any of these
- switches is used, it must be combined with <option>--interface=</option> to indicate the network interface the
- new DNS configuration belongs to. The <option>--set-dns=</option> option expects an IPv4 or IPv6 address
- specification of a DNS server to use, and may be used multiple times to define multiple servers for the same
- interface. The <option>--set-domain=</option> option expects a valid DNS domain, possibly prefixed with
- <literal>~</literal>, and configures a per-interface search or route-only domain. It may be used multiple times
- to configure multiple such domains. The <option>--set-llmnr=</option>, <option>--set-mdns=</option> and
- <option>--set-dnssec=</option> options may be used to configure the per-interface LLMNR, MulticastDNS and
- DNSSEC settings. Finally, <option>--set-nta=</option> may be used to configure additional per-interface DNSSEC
- NTA domains and may also be used multiple times. For details about these settings, their possible values and
- their effect, see the corresponding options in
+ through external means. The <option>dns</option> command expects IPv4 or IPv6 address specifications of DNS
+ servers to use. The <option>domain</option> command expects valid DNS domains, possibly prefixed with
+ <literal>~</literal>, and configures a per-interface search or route-only domain. The <option>llmnr</option>,
+ <option>mdns</option>, <option>dnssec</option> and <option>dnsovertls</option> commands may be used to configure
+ the per-interface LLMNR, MulticastDNS, DNSSEC and DNSOverTLS settings. Finally, <option>nta</option> command
+ may be used to configure additional per-interface DNSSEC NTA domains. For details about these settings, their
+ possible values and their effect, see the corresponding options in
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--revert</option></term>
-
- <listitem><para>Revert the per-interface DNS configuration. This option must be combined with
- <option>--interface=</option> to indicate the network interface the DNS configuration shall be reverted on. If
- the DNS configuration is reverted all per-interface DNS setting are reset to their defaults, undoing all
- effects of <option>--set-dns=</option>, <option>--set-domain=</option>, <option>--set-llmnr=</option>,
- <option>--set-mdns=</option>, <option>--set-dnssec=</option>, <option>--set-nta=</option>. Note that when a
- network interface disappears all configuration is lost automatically, an explicit reverting is not necessary in
- that case.</para></listitem>
+ <term><option>revert <replaceable>LINK</replaceable></option></term>
+
+ <listitem><para>Revert the per-interface DNS configuration. If the DNS configuration is reverted all
+ per-interface DNS setting are reset to their defaults, undoing all effects of <option>dns</option>,
+ <option>domain</option>, <option>llmnr</option>, <option>mdns</option>, <option>dnssec</option>,
+ <option>dnsovertls</option>, <option>nta</option>. Note that when a network interface disappears all
+ configuration is lost automatically, an explicit reverting is not necessary in that case.</para></listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="help" />
- <xi:include href="standard-options.xml" xpointer="version" />
- <xi:include href="standard-options.xml" xpointer="no-pager" />
</variablelist>
</refsect1>
<refsect1>
+ <title>Compatibility with <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry></title>
+
+ <para><command>resolvectl</command> is a multi-call binary. When invoked as <literal>resolvconf</literal>
+ (generally achieved by means of a symbolic link of this name to the <command>resolvectl</command> binary) it
+ is run in a limited <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ compatibility mode. It accepts mostly the same arguments and pushes all data into
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ similar to how <option>dns</option> and <option>domain</option> commands operate. Note that
+ <command>systemd-resolved.service</command> is the only supported backend, which is different from other
+ implementations of this command. Note that not all operations supported by other implementations are supported
+ natively. Specifically:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-a</option></term>
+ <listitem><para>Registers per-interface DNS configuration data with
+ <command>systemd-resolved</command>. Expects a network interface name as only command line argument. Reads
+ <citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> compatible DNS
+ configuration data from its standard input. Relevant fields are <literal>nameserver</literal> and
+ <literal>domain</literal>/<literal>search</literal>. This command is mostly identical to invoking
+ <command>resolvectl</command> with a combination of <option>dns</option> and
+ <option>domain</option> commands.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d</option></term>
+ <listitem><para>Unregisters per-interface DNS configuration data with <command>systemd-resolved</command>. This
+ command is mostly identical to invoking <command>resolvectl revert</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-f</option></term>
+
+ <listitem><para>When specified <option>-a</option> and <option>-d</option> will not complain about missing
+ network interfaces and will silently execute no operation in that case.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-x</option></term>
+
+ <listitem><para>This switch for "exclusive" operation is supported only partially. It is mapped to an
+ additional configured search domain of <literal>~.</literal> — i.e. ensures that DNS traffic is preferably
+ routed to the DNS servers on this interface, unless there are other, more specific domains configured on other
+ interfaces.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-m</option></term>
+ <term><option>-p</option></term>
+
+ <listitem><para>These switches are not supported and are silently ignored.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-u</option></term>
+ <term><option>-I</option></term>
+ <term><option>-i</option></term>
+ <term><option>-l</option></term>
+ <term><option>-R</option></term>
+ <term><option>-r</option></term>
+ <term><option>-v</option></term>
+ <term><option>-V</option></term>
+ <term><option>--enable-updates</option></term>
+ <term><option>--disable-updates</option></term>
+ <term><option>--are-updates-enabled</option></term>
+
+ <listitem><para>These switches are not supported and the command will fail if used.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>See <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry> for details on this command line options.</para>
+ </refsect1>
+
+ <refsect1>
<title>Examples</title>
<example>
<title>Retrieve the addresses of the <literal>www.0pointer.net</literal> domain</title>
- <programlisting>$ systemd-resolve www.0pointer.net
+ <programlisting>$ resolvectl query www.0pointer.net
www.0pointer.net: 2a01:238:43ed:c300:10c3:bcf3:3266:da74
85.214.157.71
@@ -417,7 +370,7 @@ www.0pointer.net: 2a01:238:43ed:c300:10c3:bcf3:3266:da74
<example>
<title>Retrieve the domain of the <literal>85.214.157.71</literal> IP address</title>
- <programlisting>$ systemd-resolve 85.214.157.71
+ <programlisting>$ resolvectl query 85.214.157.71
85.214.157.71: gardel.0pointer.net
-- Information acquired via protocol DNS in 1.2997s.
@@ -428,7 +381,7 @@ www.0pointer.net: 2a01:238:43ed:c300:10c3:bcf3:3266:da74
<example>
<title>Retrieve the MX record of the <literal>yahoo.com</literal> domain</title>
- <programlisting>$ systemd-resolve -t MX yahoo.com --legend=no
+ <programlisting>$ resolvectl --legend=no -t MX query yahoo.com
yahoo.com. IN MX 1 mta7.am0.yahoodns.net
yahoo.com. IN MX 1 mta6.am0.yahoodns.net
yahoo.com. IN MX 1 mta5.am0.yahoodns.net
@@ -438,7 +391,7 @@ yahoo.com. IN MX 1 mta5.am0.yahoodns.net
<example>
<title>Resolve an SRV service</title>
- <programlisting>$ systemd-resolve --service _xmpp-server._tcp gmail.com
+ <programlisting>$ resolvectl service _xmpp-server._tcp gmail.com
_xmpp-server._tcp/gmail.com: alt1.xmpp-server.l.google.com:5269 [priority=20, weight=0]
173.194.210.125
alt4.xmpp-server.l.google.com:5269 [priority=20, weight=0]
@@ -450,7 +403,7 @@ _xmpp-server._tcp/gmail.com: alt1.xmpp-server.l.google.com:5269 [priority=20, we
<example>
<title>Retrieve a PGP key</title>
- <programlisting>$ systemd-resolve --openpgp zbyszek@fedoraproject.org
+ <programlisting>$ resolvectl openpgp zbyszek@fedoraproject.org
d08ee310438ca124a6149ea5cc21b6313b390dce485576eff96f8722._openpgpkey.fedoraproject.org. IN OPENPGPKEY
mQINBFBHPMsBEACeInGYJCb+7TurKfb6wGyTottCDtiSJB310i37/6ZYoeIay/5soJjlMyf
MFQ9T2XNT/0LM6gTa0MpC1st9LnzYTMsT6tzRly1D1UbVI6xw0g0vE5y2Cjk3xUwAynCsSs
@@ -459,10 +412,10 @@ d08ee310438ca124a6149ea5cc21b6313b390dce485576eff96f8722._openpgpkey.fedoraproje
</example>
<example>
- <title>Retrieve a TLS key (<literal>=tcp</literal> and
+ <title>Retrieve a TLS key (<literal>tcp</literal> and
<literal>:443</literal> could be skipped)</title>
- <programlisting>$ systemd-resolve --tlsa=tcp fedoraproject.org:443
+ <programlisting>$ resolvectl tlsa tcp fedoraproject.org:443
_443._tcp.fedoraproject.org IN TLSA 0 0 1 19400be5b7a31fb733917700789d2f0a2471c0c9d506c0e504c06c16d7cb17c0
-- Cert. usage: CA constraint
-- Selector: Full Certificate
@@ -477,7 +430,8 @@ _443._tcp.fedoraproject.org IN TLSA 0 0 1 19400be5b7a31fb733917700789d2f0a2471c0
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.dnssd</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index 451b9cdd01..c36c303abc 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="resolved.conf" conditional='ENABLE_RESOLVE'
@@ -28,15 +11,6 @@
<refentryinfo>
<title>resolved.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -220,6 +194,38 @@
</varlistentry>
<varlistentry>
+ <term><varname>DNSOverTLS=</varname></term>
+ <listitem>
+ <para>Takes false or
+ <literal>opportunistic</literal>. When set to <literal>opportunistic</literal>
+ DNS request are attempted to send encrypted with DNS-over-TLS.
+ If the DNS server does not support TLS, DNS-over-TLS is disabled.
+ Note that this mode makes DNS-over-TLS vulnerable to "downgrade"
+ attacks, where an attacker might be able to trigger a downgrade
+ to non-encrypted mode by synthesizing a response that suggests
+ DNS-over-TLS was not supported. If set to false, DNS lookups
+ are send over UDP.</para>
+
+ <para>Note that DNS-over-TLS requires additional data to be
+ send for setting up an encrypted connection, and thus results
+ in a small DNS look-up time penalty.</para>
+
+ <para>Note as the resolver is not capable of authenticating
+ the server, it is vulnerable for "man-in-the-middle" attacks.</para>
+
+ <para>In addition to this global DNSOverTLS setting
+ <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ also maintains per-link DNSOverTLS settings. For system DNS
+ servers (see above), only the global DNSOverTLS setting is in
+ effect. For per-link DNS servers the per-link
+ setting is in effect, unless it is unset in which case the
+ global setting is used instead.</para>
+
+ <para>Defaults to off.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>Cache=</varname></term>
<listitem><para>Takes a boolean argument. If "yes" (the default), resolving a domain name which already got
queried earlier will return the previous result as long as it is still valid, and thus does not result in a new
diff --git a/man/rules/meson.build b/man/rules/meson.build
index 84b911b365..9458a4012d 100644
--- a/man/rules/meson.build
+++ b/man/rules/meson.build
@@ -25,6 +25,7 @@ manpages = [
['kernel-command-line', '7', [], ''],
['kernel-install', '8', [], ''],
['libudev', '3', [], ''],
+ ['loader.conf', '5', [], 'ENABLE_EFI'],
['locale.conf', '5', [], ''],
['localectl', '1', [], 'ENABLE_LOCALED'],
['localtime', '5', [], ''],
@@ -42,6 +43,8 @@ manpages = [
['nss-systemd', '8', ['libnss_systemd.so.2'], 'ENABLE_NSS_SYSTEMD'],
['os-release', '5', [], ''],
['pam_systemd', '8', [], 'HAVE_PAM'],
+ ['portablectl', '1', [], 'ENABLE_PORTABLED'],
+ ['resolvectl', '1', ['resolvconf'], 'ENABLE_RESOLVE'],
['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVE'],
['runlevel', '8', [], 'ENABLE_UTMP'],
['sd-bus-errors',
@@ -227,6 +230,14 @@ manpages = [
['sd_bus_set_connected_signal', '3', ['sd_bus_get_connected_signal'], ''],
['sd_bus_set_sender', '3', ['sd_bus_get_sender'], ''],
['sd_bus_set_watch_bind', '3', ['sd_bus_get_watch_bind'], ''],
+ ['sd_bus_slot_set_destroy_callback',
+ '3',
+ ['sd_bus_destroy_t',
+ 'sd_bus_slot_get_destroy_callback',
+ 'sd_bus_track_get_destroy_callback',
+ 'sd_bus_track_set_destroy_callback'],
+ ''],
+ ['sd_bus_slot_set_floating', '3', ['sd_bus_slot_get_floating'], ''],
['sd_bus_track_add_name',
'3',
['sd_bus_track_add_sender',
@@ -258,15 +269,21 @@ manpages = [
'3',
['sd_event_add_exit', 'sd_event_add_post', 'sd_event_handler_t'],
''],
+ ['sd_event_add_inotify',
+ '3',
+ ['sd_event_inotify_handler_t', 'sd_event_source_get_inotify_mask'],
+ ''],
['sd_event_add_io',
'3',
['sd_event_io_handler_t',
'sd_event_source',
'sd_event_source_get_io_events',
'sd_event_source_get_io_fd',
+ 'sd_event_source_get_io_fd_own',
'sd_event_source_get_io_revents',
'sd_event_source_set_io_events',
- 'sd_event_source_set_io_fd'],
+ 'sd_event_source_set_io_fd',
+ 'sd_event_source_set_io_fd_own'],
''],
['sd_event_add_signal',
'3',
@@ -301,6 +318,10 @@ manpages = [
'3',
['sd_event_source_get_description'],
''],
+ ['sd_event_source_set_destroy_callback',
+ '3',
+ ['sd_event_destroy_t', 'sd_event_source_get_destroy_callback'],
+ ''],
['sd_event_source_set_enabled',
'3',
['SD_EVENT_OFF',
@@ -519,6 +540,7 @@ manpages = [
['systemd-ask-password', '1', [], ''],
['systemd-backlight@.service', '8', ['systemd-backlight'], 'ENABLE_BACKLIGHT'],
['systemd-binfmt.service', '8', ['systemd-binfmt'], 'ENABLE_BINFMT'],
+ ['systemd-boot', '7', ['sd-boot'], 'ENABLE_EFI'],
['systemd-cat', '1', [], ''],
['systemd-cgls', '1', [], ''],
['systemd-cgtop', '1', [], ''],
@@ -571,8 +593,14 @@ manpages = [
'8',
['systemd-journal-gatewayd', 'systemd-journal-gatewayd.socket'],
'HAVE_MICROHTTPD'],
- ['systemd-journal-remote', '8', [], 'HAVE_MICROHTTPD'],
- ['systemd-journal-upload', '8', [], 'HAVE_MICROHTTPD'],
+ ['systemd-journal-remote.service',
+ '8',
+ ['systemd-journal-remote', 'systemd-journal-remote.socket'],
+ 'HAVE_MICROHTTPD'],
+ ['systemd-journal-upload.service',
+ '8',
+ ['systemd-journal-upload'],
+ 'HAVE_MICROHTTPD'],
['systemd-journald.service',
'8',
['systemd-journald',
@@ -602,6 +630,7 @@ manpages = [
['systemd-notify', '1', [], ''],
['systemd-nspawn', '1', [], ''],
['systemd-path', '1', [], ''],
+ ['systemd-portabled.service', '8', ['systemd-portabled'], 'ENABLE_PORTABLED'],
['systemd-quotacheck.service',
'8',
['systemd-quotacheck'],
@@ -612,7 +641,6 @@ manpages = [
'ENABLE_RANDOMSEED'],
['systemd-rc-local-generator', '8', [], ''],
['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''],
- ['systemd-resolve', '1', [], 'ENABLE_RESOLVE'],
['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVE'],
['systemd-rfkill.service',
'8',
@@ -626,7 +654,8 @@ manpages = [
'8',
['systemd-hibernate.service',
'systemd-hybrid-sleep.service',
- 'systemd-sleep'],
+ 'systemd-sleep',
+ 'systemd-suspend-then-hibernate.service'],
''],
['systemd-sysctl.service', '8', ['systemd-sysctl'], ''],
['systemd-system-update-generator', '8', [], ''],
@@ -636,6 +665,10 @@ manpages = [
''],
['systemd-sysusers', '8', ['systemd-sysusers.service'], ''],
['systemd-sysv-generator', '8', [], 'HAVE_SYSV_COMPAT'],
+ ['systemd-time-wait-sync.service',
+ '8',
+ ['systemd-time-wait-sync'],
+ 'ENABLE_TIMESYNCD'],
['systemd-timedated.service', '8', ['systemd-timedated'], 'ENABLE_TIMEDATED'],
['systemd-timesyncd.service', '8', ['systemd-timesyncd'], 'ENABLE_TIMESYNCD'],
['systemd-tmpfiles',
@@ -692,13 +725,14 @@ manpages = [
['systemd.socket', '5', [], ''],
['systemd.special', '7', [], ''],
['systemd.swap', '5', [], ''],
+ ['systemd.syntax', '7', [], ''],
['systemd.target', '5', [], ''],
['systemd.time', '7', [], ''],
['systemd.timer', '5', [], ''],
['systemd.unit', '5', [], ''],
['sysusers.d', '5', [], 'ENABLE_SYSUSERS'],
['telinit', '8', [], ''],
- ['timedatectl', '1', [], 'ENABLE_TIMEDATED'],
+ ['timedatectl', '1', [], 'ENABLE_TIMEDATECTL'],
['timesyncd.conf', '5', ['timesyncd.conf.d'], 'ENABLE_TIMESYNCD'],
['tmpfiles.d', '5', [], ''],
['udev', '7', [], ''],
diff --git a/man/runlevel.xml b/man/runlevel.xml
index 596307af9f..8b5025da4d 100644
--- a/man/runlevel.xml
+++ b/man/runlevel.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="runlevel"
@@ -30,15 +13,6 @@
<refentryinfo>
<title>runlevel</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd-bus-errors.xml b/man/sd-bus-errors.xml
index b1f24381dd..fdd2261fe9 100644
--- a/man/sd-bus-errors.xml
+++ b/man/sd-bus-errors.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd-bus-errors">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd-bus-errors</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd-bus.xml b/man/sd-bus.xml
index 48d62d466f..1f3d037c10 100644
--- a/man/sd-bus.xml
+++ b/man/sd-bus.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd-bus" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd-bus</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Documentation</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd-daemon.xml b/man/sd-daemon.xml
index 151d89e698..a404213f44 100644
--- a/man/sd-daemon.xml
+++ b/man/sd-daemon.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd-daemon"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd-daemon</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd-event.xml b/man/sd-event.xml
index 2518050570..65bc3f8891 100644
--- a/man/sd-event.xml
+++ b/man/sd-event.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd-event" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd-event</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -75,6 +49,7 @@
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
@@ -165,6 +140,7 @@
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd-id128.xml b/man/sd-id128.xml
index bd27237978..fbcf4bf367 100644
--- a/man/sd-id128.xml
+++ b/man/sd-id128.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="sd-id128"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd-id128</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -127,7 +101,6 @@ int main(int argc, char **argv) {
}
</programlisting>
-
<para><function>SD_ID128_CONST_STR()</function> may be used to
convert constant 128-bit IDs into constant strings for output. The
following example code will output the string
diff --git a/man/sd-journal.xml b/man/sd-journal.xml
index 52f99c7f4c..8bfcb90ca0 100644
--- a/man/sd-journal.xml
+++ b/man/sd-journal.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="sd-journal"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd-journal</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd-login.xml b/man/sd-login.xml
index 5b99d9e281..93fd9ea782 100644
--- a/man/sd-login.xml
+++ b/man/sd-login.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd-login" conditional='HAVE_PAM'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd-login</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_booted.xml b/man/sd_booted.xml
index 54a9de894b..ace5417c2c 100644
--- a/man/sd_booted.xml
+++ b/man/sd_booted.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_booted"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_booted</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_add_match.xml b/man/sd_bus_add_match.xml
index f11d078284..9137ef977c 100644
--- a/man/sd_bus_add_match.xml
+++ b/man/sd_bus_add_match.xml
@@ -5,22 +5,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2016 Julian Orth
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Julian Orth
-->
<refentry id="sd_bus_add_match">
@@ -28,14 +13,6 @@
<refentryinfo>
<title>sd_bus_add_match</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <firstname>Julian</firstname>
- <surname>Orth</surname>
- <email>ju.orth@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -136,7 +113,7 @@
name), from which the match string is internally generated. Optionally, these parameters may be specified as
<constant>NULL</constant> in which case the relevant field of incoming signals is not tested.</para>
- <para><function>sd_bus_match_signal_async()</function> is combines the signal matching logic of
+ <para><function>sd_bus_match_signal_async()</function> combines the signal matching logic of
<function>sd_bus_match_signal()</function> with the asynchronous behaviour of
<function>sd_bus_add_match_async()</function>.</para>
@@ -145,7 +122,9 @@
at a later time with
<citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If specified
as <constant>NULL</constant> the lifetime of the match is bound to the lifetime of the bus object itself, and the
- match cannot be removed independently.</para>
+ match is generally not removed independently. See
+ <citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
+ details.</para>
<para>The message <parameter>m</parameter> passed to the callback is only borrowed, that is, the callback should
not call <citerefentry><refentrytitle>sd_bus_message_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@@ -188,7 +167,8 @@
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_set_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_set_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_bus_creds_get_pid.xml b/man/sd_bus_creds_get_pid.xml
index d08a24ea80..1ca28e7a19 100644
--- a/man/sd_bus_creds_get_pid.xml
+++ b/man/sd_bus_creds_get_pid.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_creds_get_pid">
+<refentry id="sd_bus_creds_get_pid" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_creds_get_pid</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -542,16 +516,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_creds_get_pid()</function> and the other
- functions described here are available as a shared library, which
- can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_creds_new_from_pid.xml b/man/sd_bus_creds_new_from_pid.xml
index 5cdff073ea..2fc7a62c6b 100644
--- a/man/sd_bus_creds_new_from_pid.xml
+++ b/man/sd_bus_creds_new_from_pid.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_creds_new_from_pid">
+<refentry id="sd_bus_creds_new_from_pid" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_creds_new_from_pid</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -328,16 +302,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_creds_new_from_pid()</function> and the
- other calls described here are available as a shared library,
- which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_default.xml b/man/sd_bus_default.xml
index 62520ff4dd..53cc9d7768 100644
--- a/man/sd_bus_default.xml
+++ b/man/sd_bus_default.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_default">
+<refentry id="sd_bus_default" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_default</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -219,21 +193,26 @@
<citerefentry><refentrytitle>sd_bus_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
to drop the reference.</para>
- <para>Queued but unwritten/unread messages also keep a reference
- to their bus connection object. For this reason, even if an
- application dropped all references to a bus connection, it might
- not get destroyed right away. Until all incoming queued
- messages are read, and until all outgoing unwritten messages are
- written, the bus object will stay
- alive. <function>sd_bus_flush()</function> may be used to write
- all outgoing queued messages so they drop their references. To
- flush the unread incoming messages, use
- <function>sd_bus_close()</function>, which will also close the bus
- connection. When using the default bus logic, it is a good idea to
- first invoke <function>sd_bus_flush()</function> followed by
- <function>sd_bus_close()</function> when a thread or process
- terminates, and thus its bus connection object should be
- freed.</para>
+ <para>Queued but unwritten/unread messages keep a reference to their bus connection object. For this reason, even
+ if an application dropped all references to a bus connection, it might not get destroyed right away. Until all
+ incoming queued messages are read, and until all outgoing unwritten messages are written, the bus object will stay
+ alive. <function>sd_bus_flush()</function> may be used to write all outgoing queued messages so they drop their
+ references. To flush the unread incoming messages, use <function>sd_bus_close()</function>, which will also close
+ the bus connection. When using the default bus logic, it is a good idea to first invoke
+ <function>sd_bus_flush()</function> followed by <function>sd_bus_close()</function> when a thread or process
+ terminates, and thus its bus connection object should be freed.</para>
+
+ <para>Normally, slot objects (as created by
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry> and similar
+ calls) keep a reference to their bus connection object, too. Thus, as long as a bus slot object remains referenced
+ its bus object will remain allocated too. Optionally, bus slot objects may be placed in "floating" mode. When in
+ floating mode the life cycle of the bus slot object is bound to the bus object, i.e. when the bus object is freed
+ the bus slot object is automatically unreferenced too. The floating state of a slot object may be controlled
+ explicitly with
+ <citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ though usually floating bus slot objects are created by passing <constant>NULL</constant> as the
+ <parameter>slot</parameter> parameter of <function>sd_bus_add_match()</function> and related calls, thus indicating
+ that the caller is not directly interested in referencing and managing the bus slot object.</para>
<para>The life cycle of the default bus connection should be the
responsibility of the code that creates/owns the thread the
@@ -289,16 +268,7 @@
by returned. See <citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_open_user()</function> and the other
- functions described here are available as a shared library, which
- can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_error.xml b/man/sd_bus_error.xml
index ef40178f1f..77cb16e143 100644
--- a/man/sd_bus_error.xml
+++ b/man/sd_bus_error.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_error">
+<refentry id="sd_bus_error" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_error</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -365,15 +339,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_set_error()</function> and other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_error_add_map.xml b/man/sd_bus_error_add_map.xml
index 072b31c7d3..b4b3b1bd17 100644
--- a/man/sd_bus_error_add_map.xml
+++ b/man/sd_bus_error_add_map.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_bus_error_add_map">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_bus_error_add_map</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_get_fd.xml b/man/sd_bus_get_fd.xml
index 2e867b0bf7..a5d49074b3 100644
--- a/man/sd_bus_get_fd.xml
+++ b/man/sd_bus_get_fd.xml
@@ -5,22 +5,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2016 Julian Orth
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Julian Orth
-->
<refentry id="sd_bus_get_fd">
@@ -28,14 +13,6 @@
<refentryinfo>
<title>sd_bus_get_fd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <firstname>Julian</firstname>
- <surname>Orth</surname>
- <email>ju.orth@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_get_n_queued_read.xml b/man/sd_bus_get_n_queued_read.xml
index 32be403fc5..b8788769ec 100644
--- a/man/sd_bus_get_n_queued_read.xml
+++ b/man/sd_bus_get_n_queued_read.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2018 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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="sd_bus_get_n_queued_read">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_bus_get_fd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_is_open.xml b/man/sd_bus_is_open.xml
index 9bc671fc37..69cbb29284 100644
--- a/man/sd_bus_is_open.xml
+++ b/man/sd_bus_is_open.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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="sd_bus_is_open">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_bus_is_open</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_message_append.xml b/man/sd_bus_message_append.xml
index 3fba212014..b70ec8309c 100644
--- a/man/sd_bus_message_append.xml
+++ b/man/sd_bus_message_append.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_bus_message_append"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_bus_message_append</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -264,15 +238,7 @@ sd_bus_message_append(m, "ynqiuxtd", y, n, q, i, u, x, t, d);</programlisting>
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_open_user()</function> and other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd-bus</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_append_array.xml b/man/sd_bus_message_append_array.xml
index 2b9f3d1832..4c1142eeb0 100644
--- a/man/sd_bus_message_append_array.xml
+++ b/man/sd_bus_message_append_array.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_bus_message_append_array"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_bus_message_append_array</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -189,15 +163,7 @@
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_append_array()</function> and other
- functions described here are available as a shared library, which
- can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_append_basic.xml b/man/sd_bus_message_append_basic.xml
index bec126836e..6c76569012 100644
--- a/man/sd_bus_message_append_basic.xml
+++ b/man/sd_bus_message_append_basic.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_message_append_basic">
+<refentry id="sd_bus_message_append_basic" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_message_append_basic</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -273,15 +247,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_bus_append_basic()</function> function
- described here is available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_append_string_memfd.xml b/man/sd_bus_message_append_string_memfd.xml
index 470c62d4e1..37be79c976 100644
--- a/man/sd_bus_message_append_string_memfd.xml
+++ b/man/sd_bus_message_append_string_memfd.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_bus_message_append_string_memfd"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_bus_message_append_string_memfd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -132,14 +106,7 @@
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
- <refsect1>
- <title>Notes</title>
-
- <para>The functions described here are available as a shared library,
- which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_append_strv.xml b/man/sd_bus_message_append_strv.xml
index 21feafd501..9cd4513ab1 100644
--- a/man/sd_bus_message_append_strv.xml
+++ b/man/sd_bus_message_append_strv.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_bus_message_append_strv"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_bus_message_append_strv</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -93,15 +67,7 @@
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_bus_append_append_strv()</function> function
- described here is available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_get_cookie.xml b/man/sd_bus_message_get_cookie.xml
index d87d361501..cc9a445c06 100644
--- a/man/sd_bus_message_get_cookie.xml
+++ b/man/sd_bus_message_get_cookie.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_message_get_cookie">
+<refentry id="sd_bus_message_get_cookie"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_message_get_cookie</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -124,16 +99,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_bus_message_get_cookie()</function> and
- <function>sd_bus_message_get_reply_cookie()</function> interfaces
- are available as a shared library, which can be compiled and
- linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_get_monotonic_usec.xml b/man/sd_bus_message_get_monotonic_usec.xml
index 9d619e5f68..06ea227d88 100644
--- a/man/sd_bus_message_get_monotonic_usec.xml
+++ b/man/sd_bus_message_get_monotonic_usec.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_message_get_monotonic_usec">
+<refentry id="sd_bus_message_get_monotonic_usec"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_message_get_monotonic_usec</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -154,18 +129,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The
- <function>sd_bus_message_get_monotonic_usec()</function>,
- <function>sd_bus_message_get_realtime_usec()</function>, and
- <function>sd_bus_message_get_seqnum()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_read_basic.xml b/man/sd_bus_message_read_basic.xml
index eb1750b2db..c0e04667ca 100644
--- a/man/sd_bus_message_read_basic.xml
+++ b/man/sd_bus_message_read_basic.xml
@@ -5,22 +5,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2016 Julian Orth
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Julian Orth
-->
<refentry id="sd_bus_message_read_basic">
@@ -28,14 +13,6 @@
<refentryinfo>
<title>sd_bus_message_read_basic</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <firstname>Julian</firstname>
- <surname>Orth</surname>
- <email>ju.orth@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_message_set_destination.xml b/man/sd_bus_message_set_destination.xml
index ff69a23152..626272b0aa 100644
--- a/man/sd_bus_message_set_destination.xml
+++ b/man/sd_bus_message_set_destination.xml
@@ -3,39 +3,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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="sd_bus_message_set_destination">
+<refentry id="sd_bus_message_set_destination" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_message_set_destination</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -112,16 +86,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_bus_message_set_destination()</function> and
- <function>sd_bus_message_set_sender()</function> interfaces
- are available as a shared library, which can be compiled and
- linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_negotiate_fds.xml b/man/sd_bus_negotiate_fds.xml
index 5841c2dad6..a106bfb16e 100644
--- a/man/sd_bus_negotiate_fds.xml
+++ b/man/sd_bus_negotiate_fds.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_negotiate_fds">
+<refentry id="sd_bus_negotiate_fds" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_negotiate_fds</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -153,15 +127,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_negotiate_fds()</function> and the other
- functions described here are available as a shared library, which
- can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_new.xml b/man/sd_bus_new.xml
index 57e9f4a9cf..207291408e 100644
--- a/man/sd_bus_new.xml
+++ b/man/sd_bus_new.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_new">
+<refentry id="sd_bus_new" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_new</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -165,15 +139,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_new()</function> and other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_path_encode.xml b/man/sd_bus_path_encode.xml
index 1c898b4fab..86e255e573 100644
--- a/man/sd_bus_path_encode.xml
+++ b/man/sd_bus_path_encode.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_bus_path_encode">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_bus_path_encode</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_process.xml b/man/sd_bus_process.xml
index d9731f332c..33afa0a3b5 100644
--- a/man/sd_bus_process.xml
+++ b/man/sd_bus_process.xml
@@ -5,22 +5,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2016 Julian Orth
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Julian Orth
-->
<refentry id="sd_bus_process">
@@ -28,14 +13,6 @@
<refentryinfo>
<title>sd_bus_process</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <firstname>Julian</firstname>
- <surname>Orth</surname>
- <email>ju.orth@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_request_name.xml b/man/sd_bus_request_name.xml
index 9e668f0b02..54a14c877c 100644
--- a/man/sd_bus_request_name.xml
+++ b/man/sd_bus_request_name.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_bus_request_name">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_bus_request_name</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -124,7 +98,7 @@
<para><function>sd_bus_request_name()</function> operates in a synchronous fashion: a message requesting the name
is sent to the bus broker, and the call waits until the broker responds.</para>
- <para><function>sd_bus_request_name_async()</function> is an asynchronous version of of
+ <para><function>sd_bus_request_name_async()</function> is an asynchronous version of
<function>sd_bus_release_name()</function>. Instead of waiting for the request to complete, the request message is
enqueued. The specified <parameter>callback</parameter> will be called when the broker's response is received. If
the parameter is specified as <constant>NULL</constant> a default implementation is used instead which will
diff --git a/man/sd_bus_set_connected_signal.xml b/man/sd_bus_set_connected_signal.xml
index 9374dac3a5..b392e0f4c4 100644
--- a/man/sd_bus_set_connected_signal.xml
+++ b/man/sd_bus_set_connected_signal.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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="sd_bus_set_connected_signal">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_bus_set_connected_signal</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_set_sender.xml b/man/sd_bus_set_sender.xml
index 38efda7286..e35af282c0 100644
--- a/man/sd_bus_set_sender.xml
+++ b/man/sd_bus_set_sender.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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="sd_bus_set_sender">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_bus_set_sender</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_set_watch_bind.xml b/man/sd_bus_set_watch_bind.xml
index 5e6a6fa588..d19f6b9212 100644
--- a/man/sd_bus_set_watch_bind.xml
+++ b/man/sd_bus_set_watch_bind.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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="sd_bus_set_watch_bind">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_bus_set_watch_bind</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_slot_set_destroy_callback.xml b/man/sd_bus_slot_set_destroy_callback.xml
new file mode 100644
index 0000000000..a54b7e2d61
--- /dev/null
+++ b/man/sd_bus_slot_set_destroy_callback.xml
@@ -0,0 +1,131 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_bus_slot_set_destroy_callback"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_bus_slot_set_destroy_callback</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_slot_set_destroy_callback</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_slot_set_destroy_callback</refname>
+ <refname>sd_bus_slot_get_destroy_callback</refname>
+ <refname>sd_bus_track_set_destroy_callback</refname>
+ <refname>sd_bus_track_get_destroy_callback</refname>
+ <refname>sd_bus_destroy_t</refname>
+
+ <refpurpose>Define the callback function for resource cleanup.</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_bus_destroy_t</function>)</funcdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_slot_set_destroy_callback</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ <paramdef>sd_bus_destroy_t <parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_slot_get_destroy_callback</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ <paramdef>sd_bus_destroy_t *<parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_set_destroy_callback</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>track</parameter></paramdef>
+ <paramdef>sd_bus_destroy_t <parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_get_destroy_callback</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>track</parameter></paramdef>
+ <paramdef>sd_bus_destroy_t *<parameter>callback</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_slot_set_destroy_callback()</function> sets <parameter>callback</parameter> as the callback
+ function to be called right before the bus slot object <parameter>slot</parameter> is deallocated. The
+ <parameter>userdata</parameter> pointer from the slot object will be passed as the <parameter>userdata</parameter>
+ parameter. This pointer can be set by an argument to the constructor functions, see
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>, or directly,
+ see <citerefentry><refentrytitle>sd_bus_slot_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ This callback function is called even if <parameter>userdata</parameter> is <constant>NULL</constant>. Note that
+ this callback is invoked at a time where the bus slot object itself is already invalidated, and executing
+ operations or taking new references to the bus slot object is not permissible.</para>
+
+ <para><function>sd_bus_slot_get_destroy_callback()</function> returns the current callback
+ for <parameter>slot</parameter> in the <parameter>callback</parameter> parameter.</para>
+
+ <para><function>sd_bus_track_set_destroy_callback()</function> and
+ <function>sd_bus_track_get_destroy_callback</function> provide equivalent functionality for the
+ <parameter>userdata</parameter> pointer associated with bus peer tracking objects. For details about bus peer
+ tracking objects, see
+ <citerefentry><refentrytitle>sd_bus_track_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_bus_slot_set_destroy_callback()</function> and
+ <function>sd_bus_track_set_destroy_callback()</function> return 0 or a positive integer. On failure, they return a
+ negative errno-style error code.</para>
+
+ <para><function>sd_bus_slot_get_destroy_callback()</function> and
+ <function>sd_bus_track_get_destroy_callback</function> return positive if the destroy callback function is set, 0
+ if not. On failure, they return a negative errno-style error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The <parameter>slot</parameter> or <parameter>track</parameter> parameter is
+ <constant>NULL</constant>.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_track_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_track_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_slot_set_floating.xml b/man/sd_bus_slot_set_floating.xml
new file mode 100644
index 0000000000..77057c26cd
--- /dev/null
+++ b/man/sd_bus_slot_set_floating.xml
@@ -0,0 +1,118 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_bus_slot_set_floating" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_bus_slot_set_floating</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_slot_set_floating</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_slot_set_floating</refname>
+ <refname>sd_bus_slot_get_floating</refname>
+
+ <refpurpose>Control whether a bus slot object is "floating".</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_slot_set_floating</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ <paramdef>int <parameter>b</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_slot_get_floating</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_slot_set_floating()</function> controls whether the specified bus slot object
+ <parameter>slot</parameter> shall be "floating" or not. A floating bus slot object's lifetime is bound to the
+ lifetime of the bus object it is associated with, meaning that it remains allocated as long as the bus object
+ itself and is freed automatically when the bus object is freed. Regular (i.e. non-floating) bus slot objects keep
+ the bus referenced, hence the bus object remains allocated at least as long as there remains at least one
+ referenced bus slot object around. The floating state hence controls the direction of referencing between the bus
+ object and the bus slot objects: if floating the bus pins the bus slot, and otherwise the bus slot pins the bus
+ objects. Use <function>sd_bus_slot_set_floating()</function> to switch between both modes: if the
+ <parameter>b</parameter> parameter is zero, the slot object is considered floating, otherwise it is made a regular
+ (non-floating) slot object.</para>
+
+ <para>Bus slot objects may be allocated with calls such as
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If the
+ <parameter>slot</parameter> of these functions is non-<constant>NULL</constant> the slot object will be of the
+ regular kind (i.e. non-floating), otherwise it will be created floating. With
+ <function>sd_bus_slot_set_floating()</function> a bus slot object allocated as regular can be converted into a
+ floating object and back. This is particularly useful for creating a bus slot object, then changing parameters of
+ it, and then turning it into a floating object, whose lifecycle is managed by the bus object.</para>
+
+ <para><function>sd_bus_slot_get_floating()</function> returns the current floating state of the specified bus slot
+ object. It returns negative on error, zero if the bus slot object is a regular (non-floating) object and positive
+ otherwise.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The <parameter>slot</parameter> parameter is <constant>NULL</constant>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The bus connection has been created in a different process.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The bus object the specified bus slot object is associated with has already been freed, and
+ hence no change in the floating state can be made anymore.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_set_destroy_callback</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_track_add_name.xml b/man/sd_bus_track_add_name.xml
index 19d0115bc9..5b7f5c5b0b 100644
--- a/man/sd_bus_track_add_name.xml
+++ b/man/sd_bus_track_add_name.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_track_add_name">
+<refentry id="sd_bus_track_add_name" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_track_add_name</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -242,13 +216,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_track_add_name()</function> and the other calls described here are available as a shared library,
- which can be compiled and linked to with the <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_track_new.xml b/man/sd_bus_track_new.xml
index 4f92a5513d..0b2273ed01 100644
--- a/man/sd_bus_track_new.xml
+++ b/man/sd_bus_track_new.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_bus_track_new">
+<refentry id="sd_bus_track_new" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_track_new</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -244,13 +218,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_track_new()</function> and the other calls described here are available as a shared library,
- which can be compiled and linked to with the <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_event_add_child.xml b/man/sd_event_add_child.xml
index 15ea5de327..770072f776 100644
--- a/man/sd_event_add_child.xml
+++ b/man/sd_event_add_child.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_add_child" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_child</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -236,6 +210,7 @@
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_add_defer.xml b/man/sd_event_add_defer.xml
index 9064e63365..d259b2e39d 100644
--- a/man/sd_event_add_defer.xml
+++ b/man/sd_event_add_defer.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_add_defer" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_defer</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -207,6 +181,7 @@
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_add_inotify.xml b/man/sd_event_add_inotify.xml
new file mode 100644
index 0000000000..605863c356
--- /dev/null
+++ b/man/sd_event_add_inotify.xml
@@ -0,0 +1,191 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_event_add_inotify" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_add_inotify</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_add_inotify</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_add_inotify</refname>
+ <refname>sd_event_source_get_inotify_mask</refname>
+ <refname>sd_event_inotify_handler_t</refname>
+
+ <refpurpose>Add an "inotify" file system inode event source to an event loop</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_inotify_handler_t</function>)</funcdef>
+ <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+ <paramdef>const struct inotify_event *<parameter>event</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_add_inotify</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+ <paramdef>const char *<parameter>path</parameter></paramdef>
+ <paramdef>uint32_t <parameter>mask</parameter></paramdef>
+ <paramdef>sd_event_inotify_handler_t <parameter>handler</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_inotify_mask</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>uint32_t *<parameter>mask</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_add_inotify()</function> adds a new <citerefentry
+ project='man-pages'><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> file system inode
+ event source to an event loop. The event loop object is specified in the <parameter>event</parameter> parameter,
+ the event source object is returned in the <parameter>source</parameter> parameter. The <parameter>path</parameter>
+ parameter specifies the path of the file system inode to watch. The <parameter>handler</parameter> must reference a
+ function to call when the inode changes. The handler function will be passed the <parameter>userdata</parameter>
+ pointer, which may be chosen freely by the caller. The handler also receives a pointer to a <structname>struct
+ inotify_event</structname> structure containing information about the inode event. The <parameter>mask</parameter>
+ parameter specifie which types of inode events to watch specifically. It must contain an OR-ed combination of
+ <constant>IN_ACCESS</constant>, <constant>IN_ATTRIB</constant>, <constant>IN_CLOSE_WRITE</constant>, … flags. See
+ <citerefentry project='man-pages'><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
+ further information.</para>
+
+ <para>If multiple event sources are installed for the same inode the backing inotify watch descriptor is
+ automatically shared. The mask parameter may contain any flag defined by the inotify API, with the exception of
+ <constant>IN_MASK_ADD</constant>.</para>
+
+ <para>The handler is enabled continuously (<constant>SD_EVENT_ON</constant>), but this may be changed with
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Alternatively,
+ the <constant>IN_ONESHOT</constant> mask flag may be used to request <constant>SD_EVENT_ONESHOT</constant> mode.
+ If the handler function returns a negative error code, it will be disabled after the invocation, even if the
+ <constant>SD_EVENT_ON</constant> mode was requested before.
+ </para>
+
+ <para>As a special limitation the priority of inotify event sources may only be altered (see
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
+ in the time between creation of the event source object with <function>sd_event_add_inotify()</function> and the
+ beginning of the next event loop iteration. Attempts of changing the priority any later will be refused. Consider
+ freeing and allocating a new inotify event source to change the priority at that point.</para>
+
+ <para>To destroy an event source object use
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>, but note
+ that the event source is only removed from the event loop when all references to the event source are dropped. To
+ make sure an event source does not fire anymore, even when there's still a reference to it kept, consider disabling
+ it with
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+ <para>If the second parameter of <function>sd_event_add_inotify()</function> is passed as NULL no reference to the
+ event source object is returned. In this case the event source is considered "floating", and will be destroyed
+ implicitly when the event loop itself is destroyed.</para>
+
+ <para><function>sd_event_source_get_inotify_mask()</function> retrieves the configured inotify watch mask of an
+ event source created previously with <function>sd_event_add_inotify()</function>. It takes the event source object
+ as the <parameter>source</parameter> parameter and a pointer to a <type>uint32_t</type> variable to return the mask
+ in.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Not enough memory to allocate an object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>An invalid argument has been passed. This includes specifying a mask with
+ <constant>IN_MASK_ADD</constant> set.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The event loop is already terminated.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
+
+ <listitem><para>The passed event source is not an inotify process event source.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <example>
+ <title>A simple program that uses inotify to monitor one or two directories</title>
+
+ <programlisting><xi:include href="inotify-watch-tmp.c" parse="text" /></programlisting>
+ </example>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_event_add_io.xml b/man/sd_event_add_io.xml
index d7b26f7887..b4104a07be 100644
--- a/man/sd_event_add_io.xml
+++ b/man/sd_event_add_io.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_add_io" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_io</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -51,6 +25,8 @@
<refname>sd_event_source_get_io_revents</refname>
<refname>sd_event_source_get_io_fd</refname>
<refname>sd_event_source_set_io_fd</refname>
+ <refname>sd_event_source_get_io_fd_own</refname>
+ <refname>sd_event_source_set_io_fd_own</refname>
<refname>sd_event_source</refname>
<refname>sd_event_io_handler_t</refname>
@@ -110,6 +86,17 @@
<paramdef>int <parameter>fd</parameter></paramdef>
</funcprototype>
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_io_fd_own</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_io_fd_own</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>int <parameter>b</parameter></paramdef>
+ </funcprototype>
+
</funcsynopsis>
</refsynopsisdiv>
@@ -225,6 +212,17 @@
changes the UNIX file descriptor of an I/O event source created
previously with <function>sd_event_add_io()</function>. It takes
the event source object and the new file descriptor.</para>
+
+ <para><function>sd_event_source_set_io_fd_own()</function> controls whether the file descriptor of the event source
+ shall be closed automatically when the event source is freed, i.e. whether it shall be considered 'owned' by the
+ event source object. By default it is not closed automatically, and the application has to do this on its own. The
+ <parameter>b</parameter> parameter is a boolean parameter: if zero, the file descriptor is not closed automatically
+ when the event source is freed, otherwise it is closed.</para>
+
+ <para><function>sd_event_source_get_io_fd_own()</function> may be used to query the current setting of the file
+ descriptor ownership boolean flag as set with <function>sd_event_source_set_io_fd_own()</function>. It returns
+ positive if the file descriptor is closed automatically when the event source is destroyed, zero if not, and
+ negative on error.</para>
</refsect1>
<refsect1>
@@ -288,6 +286,7 @@
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_add_signal.xml b/man/sd_event_add_signal.xml
index 192ba95ffa..5bf7a28083 100644
--- a/man/sd_event_add_signal.xml
+++ b/man/sd_event_add_signal.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_add_signal" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_signal</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -211,6 +185,7 @@
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_add_time.xml b/man/sd_event_add_time.xml
index 56abac18cd..e139195b8e 100644
--- a/man/sd_event_add_time.xml
+++ b/man/sd_event_add_time.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_add_time" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_time</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -301,6 +275,7 @@
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_exit.xml b/man/sd_event_exit.xml
index a798a1c482..801674c675 100644
--- a/man/sd_event_exit.xml
+++ b/man/sd_event_exit.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_exit" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_exit</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_get_fd.xml b/man/sd_event_get_fd.xml
index ed648c2347..890a74333f 100644
--- a/man/sd_event_get_fd.xml
+++ b/man/sd_event_get_fd.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_get_fd" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_get_fd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_new.xml b/man/sd_event_new.xml
index 35f91cd303..61cf3d84bf 100644
--- a/man/sd_event_new.xml
+++ b/man/sd_event_new.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_new" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_new</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_now.xml b/man/sd_event_now.xml
index a17e208934..91a5a4e7c7 100644
--- a/man/sd_event_now.xml
+++ b/man/sd_event_now.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_now" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_now</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_run.xml b/man/sd_event_run.xml
index fb2687f3a4..a2611f58f3 100644
--- a/man/sd_event_run.xml
+++ b/man/sd_event_run.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 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="sd_event_run" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_run</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_set_watchdog.xml b/man/sd_event_set_watchdog.xml
index ee28caf235..e8229a4f96 100644
--- a/man/sd_event_set_watchdog.xml
+++ b/man/sd_event_set_watchdog.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_set_watchdog" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_set_watchdog</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_get_event.xml b/man/sd_event_source_get_event.xml
index 219956dcee..1a2792c637 100644
--- a/man/sd_event_source_get_event.xml
+++ b/man/sd_event_source_get_event.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_source_get_event" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_get_event</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_get_pending.xml b/man/sd_event_source_get_pending.xml
index dff6952a5a..500fa84d5e 100644
--- a/man/sd_event_source_get_pending.xml
+++ b/man/sd_event_source_get_pending.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_source_get_pending" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_get_pending</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_set_description.xml b/man/sd_event_source_set_description.xml
index ad855e6f89..054bf2091f 100644
--- a/man/sd_event_source_set_description.xml
+++ b/man/sd_event_source_set_description.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_source_set_description" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_description</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_set_destroy_callback.xml b/man/sd_event_source_set_destroy_callback.xml
new file mode 100644
index 0000000000..34f7652c86
--- /dev/null
+++ b/man/sd_event_source_set_destroy_callback.xml
@@ -0,0 +1,112 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_event_source_set_destroy_callback"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_set_destroy_callback</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_set_destroy_callback</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_set_destroy_callback</refname>
+ <refname>sd_event_source_get_destroy_callback</refname>
+ <refname>sd_event_destroy_t</refname>
+
+ <refpurpose>Define the callback function for resource cleanup.</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_destroy_t</function>)</funcdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_destroy_callback</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>sd_event_destroy_t <parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_destroy_callback</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>sd_event_destroy_t *<parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_set_destroy_callback()</function> sets <parameter>callback</parameter> as the
+ callback function to be called right before the event source object <parameter>source</parameter> is
+ deallocated. The <parameter>userdata</parameter> pointer from the event source object will be passed as the
+ <parameter>userdata</parameter> parameter. This pointer can be set by an argument to the constructor functions, see
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>, or directly,
+ see
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ This callback function is called even if <parameter>userdata</parameter> is <constant>NULL</constant>. Note that
+ this callback is invoked at a time where the event source object itself is already invalidated, and executing
+ operations or taking new references to the event source object is not permissible.</para>
+
+ <para><function>sd_event_source_get_destroy_callback()</function> returns the current callback
+ for <parameter>source</parameter> in the <parameter>callback</parameter> parameter.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_event_source_set_destroy_callback()</function> returns 0 or a positive integer. On
+ failure, it returns a negative errno-style error code.</para>
+
+ <para><function>sd_event_source_get_destroy_callback()</function> returns positive if the destroy callback function
+ is set, 0 if not. On failure, returns a negative errno-style error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The <parameter>source</parameter> parameter is <constant>NULL</constant>.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libsystemd-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_set_enabled.xml b/man/sd_event_source_set_enabled.xml
index 0628c3e8e9..0fcfefa1cc 100644
--- a/man/sd_event_source_set_enabled.xml
+++ b/man/sd_event_source_set_enabled.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_source_set_enabled" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_enabled</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_set_prepare.xml b/man/sd_event_source_set_prepare.xml
index 148cab16b1..8c7925a3c3 100644
--- a/man/sd_event_source_set_prepare.xml
+++ b/man/sd_event_source_set_prepare.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_source_set_prepare" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_prepare</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_set_priority.xml b/man/sd_event_source_set_priority.xml
index 43edd76a7e..5b8924a0f0 100644
--- a/man/sd_event_source_set_priority.xml
+++ b/man/sd_event_source_set_priority.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_source_set_priority" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_priority</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -121,6 +95,12 @@
particular event sources do not starve or dominate the event
loop.</para>
+ <para>The priority of event sources may be changed at any time of their lifetime, with the exception of inotify
+ event sources (i.e. those created with
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>) whose
+ priority may only be changed in the time between their initial creation and the first subsequent event loop
+ iteration.</para>
+
<para><function>sd_event_source_get_priority()</function> may be
used to query the current priority assigned to the event source
object <parameter>source</parameter>.</para>
diff --git a/man/sd_event_source_set_userdata.xml b/man/sd_event_source_set_userdata.xml
index cb317ad1d7..3bc5317ae7 100644
--- a/man/sd_event_source_set_userdata.xml
+++ b/man/sd_event_source_set_userdata.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_source_set_userdata" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_userdata</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml
index ec9e7c01fc..d1b83c57aa 100644
--- a/man/sd_event_source_unref.xml
+++ b/man/sd_event_source_unref.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_event_source_unref" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_unref</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_wait.xml b/man/sd_event_wait.xml
index 89de31d22f..6c0dfa7440 100644
--- a/man/sd_event_wait.xml
+++ b/man/sd_event_wait.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 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="sd_event_wait" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_event_wait</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_get_seats.xml b/man/sd_get_seats.xml
index b4b133ff0f..925516dc1d 100644
--- a/man/sd_get_seats.xml
+++ b/man/sd_get_seats.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_get_seats" conditional='HAVE_PAM'>
+<refentry id="sd_get_seats" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_get_seats</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -119,7 +94,6 @@
errno-style error code.</para>
</refsect1>
-
<refsect1>
<title>Errors</title>
@@ -135,18 +109,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_get_seats()</function>,
- <function>sd_get_sessions()</function>,
- <function>sd_get_uids()</function> and
- <function>sd_get_machine_names()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml
index a97beebbd5..954fd2e6a7 100644
--- a/man/sd_id128_get_machine.xml
+++ b/man/sd_id128_get_machine.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_id128_get_machine">
+<refentry id="sd_id128_get_machine" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_id128_get_machine</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -129,20 +103,14 @@
<refsect1>
<title>Return Value</title>
- <para>The two calls return 0 on success (in which case
- <parameter>ret</parameter> is filled in), or a negative
- errno-style error code.</para>
+ <para>Those calls return 0 on success (in which case <parameter>ret</parameter> is filled in),
+ or a negative errno-style error code. In particular, <function>sd_id128_get_machine()</function>
+ and <function>sd_id128_get_machine_app_specific()</function> return <constant>-ENOENT</constant>
+ if <filename>/etc/machine-id</filename> is missing, and <constant>-ENOMEDIUM</constant> if is
+ empty or all zeros.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_id128_get_machine()</function>, <function>sd_id128_get_machine_app_specific()</function>
- <function>sd_id128_get_boot()</function> and <function>sd_id128_get_invocation()</function> interfaces are
- available as a shared library, which can be compiled and linked to with the
- <literal>libsystemd</literal> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>Examples</title>
diff --git a/man/sd_id128_randomize.xml b/man/sd_id128_randomize.xml
index bdce3b18b7..4f7cd71398 100644
--- a/man/sd_id128_randomize.xml
+++ b/man/sd_id128_randomize.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_id128_randomize">
+<refentry id="sd_id128_randomize" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_id128_randomize</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -91,15 +65,7 @@
errno-style error code.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_id128_randomize()</function> interface is
- available as a shared library, which can be compiled and linked to
- with the
- <literal>libsystemd</literal> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_id128_to_string.xml b/man/sd_id128_to_string.xml
index b82b141a3a..ca071854e5 100644
--- a/man/sd_id128_to_string.xml
+++ b/man/sd_id128_to_string.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_id128_to_string">
+<refentry id="sd_id128_to_string" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_id128_to_string</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -108,16 +82,7 @@
errno-style error code.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_id128_to_string()</function> and
- <function>sd_id128_from_string()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <literal>libsystemd</literal> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_is_fifo.xml b/man/sd_is_fifo.xml
index 2af17df650..05709d8bab 100644
--- a/man/sd_is_fifo.xml
+++ b/man/sd_is_fifo.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_is_fifo"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_is_fifo</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_journal_add_match.xml b/man/sd_journal_add_match.xml
index b41d6189d9..d82f71ffa8 100644
--- a/man/sd_journal_add_match.xml
+++ b/man/sd_journal_add_match.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_add_match">
+<refentry id="sd_journal_add_match" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_add_match</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -167,21 +141,7 @@
returns nothing.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>All functions listed here are thread-agnostic and only a single thread may operate
- on a given <structname>sd_journal</structname> object.</para>
-
- <para>The <function>sd_journal_add_match()</function>,
- <function>sd_journal_add_disjunction()</function>,
- <function>sd_journal_add_conjunction()</function> and
- <function>sd_journal_flush_matches()</function>
- interfaces are available as a shared library, which can
- be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>Examples</title>
@@ -202,7 +162,6 @@ int add_matches(sd_journal *j) {
sd_journal_add_disjunction(j);
sd_journal_add_match(j, "MESSAGE_ID=03bb1dab98ab4ecfbf6fff2738bdd964", 0);
}</programlisting>
-
</refsect1>
<refsect1>
diff --git a/man/sd_journal_enumerate_fields.xml b/man/sd_journal_enumerate_fields.xml
index 20005564b0..95af2c1ee0 100644
--- a/man/sd_journal_enumerate_fields.xml
+++ b/man/sd_journal_enumerate_fields.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_journal_enumerate_fields">
+<refentry id="sd_journal_enumerate_fields" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_enumerate_fields</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -115,10 +89,7 @@
<para>All functions listed here are thread-agnostic and only a single thread may operate
on a given <structname>sd_journal</structname> object.</para>
- <para>The <function>sd_journal_enumerate_fields()</function> and <function>sd_journal_restart_fields()</function>
- interfaces are available as a shared library, which can be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_get_catalog.xml b/man/sd_journal_get_catalog.xml
index 95f3e3b007..ce37e177bd 100644
--- a/man/sd_journal_get_catalog.xml
+++ b/man/sd_journal_get_catalog.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_get_catalog">
+<refentry id="sd_journal_get_catalog" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_get_catalog</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -66,7 +40,6 @@
<paramdef>char **<parameter>ret</parameter></paramdef>
</funcprototype>
-
</funcsynopsis>
</refsynopsisdiv>
@@ -118,12 +91,7 @@
single thread may operate on a given <structname>sd_journal</structname> object. Function
<function>sd_journal_get_catalog_for_message_id()</function> is thread-safe.</para>
- <para>The <function>sd_journal_get_catalog()</function> and
- <function>sd_journal_get_catalog_for_message_id()</function>
- interfaces are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_get_cursor.xml b/man/sd_journal_get_cursor.xml
index ead150ec53..6817a3cd54 100644
--- a/man/sd_journal_get_cursor.xml
+++ b/man/sd_journal_get_cursor.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_get_cursor">
+<refentry id="sd_journal_get_cursor" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_get_cursor</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -127,12 +101,7 @@
<para>All functions listed here are thread-agnostic and only a single thread may operate
on a given <structname>sd_journal</structname> object.</para>
- <para>The <function>sd_journal_get_cursor()</function> and
- <function>sd_journal_test_cursor()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_get_cutoff_realtime_usec.xml b/man/sd_journal_get_cutoff_realtime_usec.xml
index 8fd9674111..dc8e32bf81 100644
--- a/man/sd_journal_get_cutoff_realtime_usec.xml
+++ b/man/sd_journal_get_cutoff_realtime_usec.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_get_cutoff_realtime_usec">
+<refentry id="sd_journal_get_cutoff_realtime_usec" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_get_cutoff_realtime_usec</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -125,13 +99,7 @@
<para>All functions listed here are thread-agnostic and only a single thread may operate
on a given <structname>sd_journal</structname> object.</para>
- <para>The
- <function>sd_journal_get_cutoff_realtime_usec()</function> and
- <function>sd_journal_get_cutoff_monotonic_usec()</function>
- interfaces are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_get_data.xml b/man/sd_journal_get_data.xml
index 831ed0bc6e..99f9500441 100644
--- a/man/sd_journal_get_data.xml
+++ b/man/sd_journal_get_data.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_get_data">
+<refentry id="sd_journal_get_data" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_get_data</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -182,19 +156,7 @@
success or a negative errno-style error code.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_journal_get_data()</function>,
- <function>sd_journal_enumerate_data()</function>,
- <function>sd_journal_restart_data()</function>,
- <function>sd_journal_set_data_threshold()</function> and
- <function>sd_journal_get_data_threshold()</function> interfaces
- are available as a shared library, which can be compiled and
- linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>Examples</title>
@@ -217,7 +179,6 @@ int print_fields(sd_journal *j) {
printf("%.*s\n", (int) length, data);
}
…</programlisting>
-
</refsect1>
<refsect1>
diff --git a/man/sd_journal_get_fd.xml b/man/sd_journal_get_fd.xml
index b15fc1728c..7edbc4bc25 100644
--- a/man/sd_journal_get_fd.xml
+++ b/man/sd_journal_get_fd.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_get_fd">
+<refentry id="sd_journal_get_fd" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_get_fd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -212,22 +186,27 @@ else {
immediately for all journal changes. Returns 0 if there might be a
latency involved.</para>
- <para><function>sd_journal_process()</function> and
- <function>sd_journal_wait()</function> return one of
- <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
- <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
- <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 <constant>SD_JOURNAL_APPEND</constant>, it is
- sufficient to simply continue reading at the previous end of the
- journal.</para>
+ <para><function>sd_journal_process()</function> and <function>sd_journal_wait()</function> return a negative
+ errno-style error code, or one of <constant>SD_JOURNAL_NOP</constant>, <constant>SD_JOURNAL_APPEND</constant> or
+ <constant>SD_JOURNAL_INVALIDATE</constant> on success:</para>
+
+ <itemizedlist>
+ <listitem><para>If <constant>SD_JOURNAL_NOP</constant> is returned, the journal did not change since the last
+ invocation.</para></listitem>
+
+ <listitem><para>If <constant>SD_JOURNAL_APPEND</constant> is returned, new entries have been appended to the end
+ of the journal. In this case it is sufficient to simply continue reading at the previous end location of the
+ journal, to read the newly added entries.</para></listitem>
+
+ <listitem><para>If <constant>SD_JOURNAL_INVALIDATE</constant>, journal files were added to or removed from the
+ set of journal files watched (e.g. due to rotation or vacuuming), and thus entries might have appeared or
+ disappeared at arbitrary places in the log stream, possibly before or after the previous end of the log
+ stream. If <constant>SD_JOURNAL_INVALIDATE</constant> is returned, live-view UIs that want to reflect on screen
+ the precise state of the log data on disk should probably refresh their entire display (relative to the cursor of
+ the log entry on the top of the screen). Programs only interested in a strictly sequential stream of log data may
+ treat <constant>SD_JOURNAL_INVALIDATE</constant> the same way as <constant>SD_JOURNAL_APPEND</constant>, thus
+ ignoring any changes to the log view earlier than the old end of the log stream.</para></listitem>
+ </itemizedlist>
</refsect1>
<refsect1>
@@ -263,73 +242,13 @@ else {
<para>Iterating through the journal, in a live view tracking all
changes:</para>
- <programlisting>#include &lt;stdio.h&gt;
-#include &lt;string.h&gt;
-#include &lt;systemd/sd-journal.h&gt;
-
-int main(int argc, char *argv[]) {
- int r;
- sd_journal *j;
- r = sd_journal_open(&amp;j, SD_JOURNAL_LOCAL_ONLY);
- if (r &lt; 0) {
- fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
- return 1;
- }
- for (;;) {
- const void *d;
- size_t l;
- r = sd_journal_next(j);
- if (r &lt; 0) {
- fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r));
- break;
- }
- if (r == 0) {
- /* Reached the end, let's wait for changes, and try again */
- r = sd_journal_wait(j, (uint64_t) -1);
- if (r &lt; 0) {
- fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r));
- break;
- }
- continue;
- }
- r = sd_journal_get_data(j, "MESSAGE", &amp;d, &amp;l);
- if (r &lt; 0) {
- fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
- continue;
- }
- printf("%.*s\n", (int) l, (const char*) d);
- }
- sd_journal_close(j);
- return 0;
-}</programlisting>
+ <programlisting><xi:include href="journal-iterate-wait.c" parse="text" /></programlisting>
<para>Waiting with <function>poll()</function> (this
example lacks all error checking for the sake of
simplicity):</para>
- <programlisting>#include &lt;poll.h&gt;
-#include &lt;systemd/sd-journal.h&gt;
-
-int wait_for_changes(sd_journal *j) {
- struct pollfd pollfd;
- int msec;
-
- sd_journal_get_timeout(m, &amp;t);
- if (t == (uint64_t) -1)
- msec = -1;
- else {
- struct timespec ts;
- uint64_t n;
- clock_gettime(CLOCK_MONOTONIC, &amp;ts);
- n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
- msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
- }
-
- pollfd.fd = sd_journal_get_fd(j);
- pollfd.events = sd_journal_get_events(j);
- poll(&amp;pollfd, 1, msec);
- return sd_journal_process(j);
-}</programlisting>
+ <programlisting><xi:include href="journal-iterate-poll.c" parse="text" /></programlisting>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_get_realtime_usec.xml b/man/sd_journal_get_realtime_usec.xml
index 49800c34a3..2030e8372d 100644
--- a/man/sd_journal_get_realtime_usec.xml
+++ b/man/sd_journal_get_realtime_usec.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_get_realtime_usec">
+<refentry id="sd_journal_get_realtime_usec"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_get_realtime_usec</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -114,16 +89,7 @@
<function>sd_journal_get_monotonic_usec()</function>.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_journal_get_realtime_usec()</function> and
- <function>sd_journal_get_monotonic_usec()</function> interfaces
- are available as a shared library, which can be compiled and
- linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_journal_get_usage.xml b/man/sd_journal_get_usage.xml
index 63d073e119..358a62d066 100644
--- a/man/sd_journal_get_usage.xml
+++ b/man/sd_journal_get_usage.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_get_usage">
+<refentry id="sd_journal_get_usage" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_get_usage</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -85,11 +59,7 @@
<para>All functions listed here are thread-agnostic and only a single thread may operate
on a given <structname>sd_journal</structname> object.</para>
- <para>The <function>sd_journal_get_usage()</function> interface is
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_has_runtime_files.xml b/man/sd_journal_has_runtime_files.xml
index 7431190496..b7bbf224d4 100644
--- a/man/sd_journal_has_runtime_files.xml
+++ b/man/sd_journal_has_runtime_files.xml
@@ -5,38 +5,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2016 Jan Synáček
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Jan Synáček
-->
-<refentry id="sd_journal_has_runtime_files">
+<refentry id="sd_journal_has_runtime_files" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_has_runtime_files</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Jan</firstname>
- <surname>Synáček</surname>
- <email>jan.synacek@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -93,10 +69,7 @@
<para>All functions listed here are thread-agnostic and only a single thread may operate
on a given <structname>sd_journal</structname> object.</para>
- <para>Functions listed here are available as a shared library, which can be compiled and linked
- to with the <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_next.xml b/man/sd_journal_next.xml
index 18b0da048d..c0ca5a8a14 100644
--- a/man/sd_journal_next.xml
+++ b/man/sd_journal_next.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_next">
+<refentry id="sd_journal_next" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_next</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -151,14 +125,7 @@
<para>All functions listed here are thread-agnostic and only a single thread may operate
on a given <structname>sd_journal</structname> object.</para>
- <para>The <function>sd_journal_next()</function>,
- <function>sd_journal_previous()</function>,
- <function>sd_journal_next_skip()</function> and
- <function>sd_journal_previous_skip()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml
index 5e7ae45688..9f600b223f 100644
--- a/man/sd_journal_open.xml
+++ b/man/sd_journal_open.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="sd_journal_open">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>sd_journal_open</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_journal_print.xml b/man/sd_journal_print.xml
index 038d3bbbd4..f8ff7ba093 100644
--- a/man/sd_journal_print.xml
+++ b/man/sd_journal_print.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_print">
+<refentry id="sd_journal_print" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_print</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -216,15 +190,7 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
not async signal safe.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_journal_print()</function>, <function>sd_journal_printv()</function>,
- <function>sd_journal_send()</function>, <function>sd_journal_sendv()</function> and
- <function>sd_journal_perror()</function> interfaces are available as a shared library, which can be compiled and
- linked to with the <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_journal_query_unique.xml b/man/sd_journal_query_unique.xml
index fb08400f20..0bbc479f22 100644
--- a/man/sd_journal_query_unique.xml
+++ b/man/sd_journal_query_unique.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_query_unique">
+<refentry id="sd_journal_query_unique" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_query_unique</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -155,13 +129,7 @@
<para>All functions listed here are thread-agnostic and only a single thread may operate
on a given <structname>sd_journal</structname> object.</para>
- <para>The <function>sd_journal_query_unique()</function>,
- <function>sd_journal_enumerate_unique()</function> and
- <function>sd_journal_restart_unique()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_seek_head.xml b/man/sd_journal_seek_head.xml
index 7e866e8e82..86274071f5 100644
--- a/man/sd_journal_seek_head.xml
+++ b/man/sd_journal_seek_head.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_seek_head">
+<refentry id="sd_journal_seek_head" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_seek_head</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -149,15 +123,7 @@
<para>All functions listed here are thread-agnostic and only a single thread may operate
on a given <structname>sd_journal</structname> object.</para>
- <para>The <function>sd_journal_seek_head()</function>,
- <function>sd_journal_seek_tail()</function>,
- <function>sd_journal_seek_monotonic_usec()</function>,
- <function>sd_journal_seek_realtime_usec()</function>,
- and <function>sd_journal_seek_cursor()</function>
- interfaces are available as a shared library, which can
- be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_journal_stream_fd.xml b/man/sd_journal_stream_fd.xml
index 13972aea7c..de76cabb4d 100644
--- a/man/sd_journal_stream_fd.xml
+++ b/man/sd_journal_stream_fd.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="sd_journal_stream_fd">
+<refentry id="sd_journal_stream_fd" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_journal_stream_fd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -121,11 +95,7 @@
<para>Function <function>sd_journal_stream_fd()</function> is thread-safe and may be called
from multiple threads.</para>
- <para>The <function>sd_journal_stream_fd()</function> interface is
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
</refsect1>
<refsect1>
diff --git a/man/sd_listen_fds.xml b/man/sd_listen_fds.xml
index 8563a06997..6dfe716a2d 100644
--- a/man/sd_listen_fds.xml
+++ b/man/sd_listen_fds.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_listen_fds"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_listen_fds</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_login_monitor_new.xml b/man/sd_login_monitor_new.xml
index 935fca5697..23f685bb31 100644
--- a/man/sd_login_monitor_new.xml
+++ b/man/sd_login_monitor_new.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_login_monitor_new" conditional='HAVE_PAM'>
+<refentry id="sd_login_monitor_new" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_login_monitor_new</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -259,20 +234,7 @@ else {
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_login_monitor_new()</function>,
- <function>sd_login_monitor_unref()</function>,
- <function>sd_login_monitor_flush()</function>,
- <function>sd_login_monitor_get_fd()</function>,
- <function>sd_login_monitor_get_events()</function> and
- <function>sd_login_monitor_get_timeout()</function>
- interfaces are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_machine_get_class.xml b/man/sd_machine_get_class.xml
index 989fa2db0f..bacbe1455e 100644
--- a/man/sd_machine_get_class.xml
+++ b/man/sd_machine_get_class.xml
@@ -4,39 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_machine_get_class">
+<refentry id="sd_machine_get_class" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_machine_get_class</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -129,16 +103,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_machine_get_class()</function> and
- <function>sd_machine_get_ifindices()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index c28f303c7e..5d6ae65701 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_notify"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_notify</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_pid_get_owner_uid.xml b/man/sd_pid_get_owner_uid.xml
index fcedcfcd1f..9229217b0b 100644
--- a/man/sd_pid_get_owner_uid.xml
+++ b/man/sd_pid_get_owner_uid.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_pid_get_owner_uid" conditional='HAVE_PAM'>
+<refentry id="sd_pid_get_owner_uid" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_pid_get_owner_uid</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -321,24 +296,7 @@
<refsect1>
<title>Notes</title>
- <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>,
- <function>sd_pid_get_machine_name()</function>,
- <function>sd_pid_get_slice()</function>,
- <function>sd_pid_get_user_slice()</function>,
- <function>sd_peer_get_session()</function>,
- <function>sd_peer_get_unit()</function>,
- <function>sd_peer_get_user_unit()</function>,
- <function>sd_peer_get_owner_uid()</function>,
- <function>sd_peer_get_machine_name()</function>,
- <function>sd_peer_get_slice()</function> and
- <function>sd_peer_get_user_slice()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the <constant>libsystemd</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
<para>Note that the login session identifier as
returned by <function>sd_pid_get_session()</function>
diff --git a/man/sd_seat_get_active.xml b/man/sd_seat_get_active.xml
index 57a6b526f2..2fc5fdeea1 100644
--- a/man/sd_seat_get_active.xml
+++ b/man/sd_seat_get_active.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_seat_get_active" conditional='HAVE_PAM'>
+<refentry id="sd_seat_get_active" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_seat_get_active</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -188,19 +163,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_seat_get_active()</function>,
- <function>sd_seat_get_sessions()</function>,
- <function>sd_seat_can_multi_session()</function>,
- <function>sd_seat_can_tty()</function> and
- <function>sd_seat_can_graphical()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_session_is_active.xml b/man/sd_session_is_active.xml
index 14993bcd67..a0f7a93121 100644
--- a/man/sd_session_is_active.xml
+++ b/man/sd_session_is_active.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_session_is_active" conditional='HAVE_PAM'>
+<refentry id="sd_session_is_active" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_session_is_active</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -329,25 +304,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_session_is_active()</function>,
- <function>sd_session_get_state()</function>,
- <function>sd_session_get_uid()</function>,
- <function>sd_session_get_seat()</function>,
- <function>sd_session_get_service()</function>,
- <function>sd_session_get_type()</function>,
- <function>sd_session_get_class()</function>,
- <function>sd_session_get_display()</function>,
- <function>sd_session_get_remote_host()</function>,
- <function>sd_session_get_remote_user()</function> and
- <function>sd_session_get_tty()</function>
- interfaces are available as a shared library, which can
- be compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_uid_get_state.xml b/man/sd_uid_get_state.xml
index c8b62f7a43..6f4ff77130 100644
--- a/man/sd_uid_get_state.xml
+++ b/man/sd_uid_get_state.xml
@@ -4,39 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="sd_uid_get_state" conditional='HAVE_PAM'>
+<refentry id="sd_uid_get_state" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_uid_get_state</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -210,14 +185,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>Functions described here are available as a shared library,
- and can be compiled and linked to using the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- entry.</para>
- </refsect1>
+ <xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_watchdog_enabled.xml b/man/sd_watchdog_enabled.xml
index e85998c216..ad2cdd8782 100644
--- a/man/sd_watchdog_enabled.xml
+++ b/man/sd_watchdog_enabled.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sd_watchdog_enabled"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>sd_watchdog_enabled</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/shutdown.xml b/man/shutdown.xml
index 41fe71f4da..282a3bae21 100644
--- a/man/shutdown.xml
+++ b/man/shutdown.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="shutdown"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>shutdown</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/standard-conf.xml b/man/standard-conf.xml
index 673ca44edc..e1cb7d31ed 100644
--- a/man/standard-conf.xml
+++ b/man/standard-conf.xml
@@ -4,24 +4,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Zbigniew Jędrzejewski-Szmek
- Copyright 2014 Josh Triplett
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Josh Triplett
-->
<refsection>
diff --git a/man/standard-options.xml b/man/standard-options.xml
index dcc6bb89ae..bea92e89fb 100644
--- a/man/standard-options.xml
+++ b/man/standard-options.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<variablelist>
@@ -63,4 +46,13 @@
footer with hints.</para>
</listitem>
</varlistentry>
+
+ <varlistentry id='cat-config'>
+ <term><option>--cat-config</option></term>
+
+ <listitem>
+ <para>Copy the contents of config files to standard output.
+ Before each file, the filename is printed as a comment.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
diff --git a/man/sysctl.d.xml b/man/sysctl.d.xml
index ec69b4c5bb..7c8fde0dba 100644
--- a/man/sysctl.d.xml
+++ b/man/sysctl.d.xml
@@ -2,23 +2,6 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="sysctl.d"
xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +9,6 @@
<refentryinfo>
<title>sysctl.d</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 1588ca719d..d95d3726af 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemctl"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>systemctl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -583,19 +557,19 @@
<term><option>--runtime</option></term>
<listitem>
- <para>When used with <command>enable</command>,
- <command>disable</command>, <command>edit</command>,
- (and related commands), make changes only temporarily, so
- that they are lost on the next reboot. This will have the
- effect that changes are not made in subdirectories of
- <filename>/etc</filename> but in <filename>/run</filename>,
- with identical immediate effects, however, since the latter
+ <para>When used with <command>set-property</command>, make changes only
+ temporarily, so that they are lost on the next reboot.</para>
+
+ <para>Similarily, when used with <command>enable</command>, <command>mask</command>,
+ <command>edit</command> and related commands, make temporary changes, which are lost on
+ the next reboot. Changes are not made in subdirectories of <filename>/etc</filename>, but
+ in <filename>/run</filename>. The immediate effect is identical, however since the latter
is lost on reboot, the changes are lost too.</para>
- <para>Similarly, when used with
- <command>set-property</command>, make changes only
- temporarily, so that they are lost on the next
- reboot.</para>
+ <para>Note: this option cannot be used with <command>disable</command>,
+ <command>unmask</command>, <command>preset</command>, or <command>preset-all</command>,
+ because those operations sometimes need to remove symlinks under <filename>/etc</filename>
+ to have the desired effect, which would cause a persistent change.</para>
</listitem>
</varlistentry>
@@ -692,6 +666,38 @@
that are shown are additionally filtered by <option>--type=</option> and <option>--state=</option> if those
options are specified.</para>
+ <para>Produces output similar to
+ <programlisting> UNIT LOAD ACTIVE SUB DESCRIPTION
+ sys-module-fuse.device loaded active plugged /sys/module/fuse
+ -.mount loaded active mounted Root Mount
+ boot-efi.mount loaded active mounted /boot/efi
+ systemd-journald.service loaded active running Journal Service
+ systemd-logind.service loaded active running Login Service
+● user@1000.service loaded active running User Manager for UID 1000
+…
+ systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories
+
+LOAD = Reflects whether the unit definition was properly loaded.
+ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
+SUB = The low-level unit activation state, values depend on unit type.
+
+123 loaded units listed. Pass --all to see loaded but inactive units, too.
+To show all installed unit files use 'systemctl list-unit-files'.
+ </programlisting>
+ The header and the last unit of a given type are underlined if the
+ terminal supports that. A colored dot is shown next to services which
+ were masked, not found, or otherwise failed.</para>
+
+ <para>The LOAD column shows the load state, one of <constant>loaded</constant>,
+ <constant>not-found</constant>, <constant>bad-setting</constant>, <constant>error</constant>,
+ <constant>masked</constant>. The ACTIVE columns shows the general unit state, one of
+ <constant>active</constant>, <constant>reloading</constant>, <constant>inactive</constant>,
+ <constant>failed</constant>, <constant>activating</constant>, <constant>deactivating</constant>. The SUB
+ column shows the unit-type-specific detailed state of the unit, possible values vary by unit type. The list
+ of possible LOAD, ACTIVE, and SUB states is not constant and new systemd releases may both add and remove
+ values. <programlisting>systemctl --state=help</programlisting> command maybe be used to display the
+ current set of possible values.</para>
+
<para>This is the default command.</para>
</listitem>
</varlistentry>
@@ -738,7 +744,7 @@ Sun 2017-02-26 20:57:49 EST 2h 3min left Sun 2017-02-26 11:56:36 EST 6h ago
<para><emphasis>NEXT</emphasis> shows the next time the timer will run.</para>
<para><emphasis>LEFT</emphasis> shows how long till the next time the timer runs.</para>
<para><emphasis>LAST</emphasis> shows the last time the timer ran.</para>
- <para><emphasis>PASSED</emphasis> shows has long as passed since the timer laset ran.</para>
+ <para><emphasis>PASSED</emphasis> shows how long has passed since the timer last ran.</para>
<para><emphasis>UNIT</emphasis> shows the name of the timer</para>
<para><emphasis>ACTIVATES</emphasis> shows the name the service the timer activates when it runs.</para>
@@ -952,10 +958,12 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<para>The "Loaded:" line in the output will show <literal>loaded</literal> if the unit has been loaded into
memory. Other possible values for "Loaded:" include: <literal>error</literal> if there was a problem
- loading it, <literal>not-found</literal>, and <literal>masked</literal>. Along with showing the path to
- the unit file, this line will also show the enablement state. Enabled commands start at boot. See the
- full table of possible enablement states — including the definition of <literal>masked</literal> — in the
- documentation for the <command>is-enabled</command> command.
+ loading it, <literal>not-found</literal> if not unit file was found for this unit,
+ <literal>bad-setting</literal> if an essential unit file setting could not be parsed and
+ <literal>masked</literal> if the unit file has been masked. Along with showing the path to the unit file,
+ this line will also show the enablement state. Enabled commands start at boot. See the full table of
+ possible enablement states — including the definition of <literal>masked</literal> — in the documentation
+ for the <command>is-enabled</command> command.
</para>
<para>The "Active:" line shows active state. The value is usually <literal>active</literal> or
diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
index 97a9b2cca7..7aa10fc68e 100644
--- a/man/systemd-analyze.xml
+++ b/man/systemd-analyze.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-analyze"
@@ -29,21 +12,6 @@
<refentryinfo>
<title>systemd-analyze</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- <author>
- <contrib>Developer</contrib>
- <firstname>Harald</firstname>
- <surname>Hoyer</surname>
- <email>harald@redhat.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -94,6 +62,12 @@
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">cat-config</arg>
+ <arg choice="plain" rep="repeat"><replaceable>NAME</replaceable>|<replaceable>PATH</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">unit-paths</arg>
</cmdsynopsis>
<cmdsynopsis>
@@ -157,7 +131,11 @@
This information may be used to optimize boot-up times. Note that
the output might be misleading as the initialization of one
service might be slow simply because it waits for the
- initialization of another service to complete.</para>
+ initialization of another service to complete.
+ Also note: <command>systemd-analyze blame</command> doesn't display
+ results for services with <varname>Type=simple</varname>,
+ because systemd considers such services to be started immediately,
+ hence no measurement of the initialization delays can be done.</para>
<para><command>systemd-analyze critical-chain
[<replaceable>UNIT…</replaceable>]</command> prints a tree of
@@ -193,6 +171,33 @@
state. Its format is subject to change without notice and should
not be parsed by applications.</para>
+ <para><command>systemd-analyze cat-config</command> is similar
+ to <command>systemctl cat</command>, but operates on config files.
+ It will copy the contents of a config file and any drop-ins to standard
+ output, using the usual systemd set of directories and rules for
+ precedence. Each argument must be either an absolute path including
+ the prefix (such as <filename>/etc/systemd/logind.conf</filename> or
+ <filename>/usr/lib/systemd/logind.conf</filename>), or a name
+ relative to the prefix (such as <filename>systemd/logind.conf</filename>).
+ </para>
+
+ <example>
+ <title>Showing logind configuration</title>
+ <programlisting>$ systemd-analyze cat-config systemd/logind.conf
+# /etc/systemd/logind.conf
+...
+[Login]
+NAutoVTs=8
+...
+
+# /usr/lib/systemd/logind.conf.d/20-test.conf
+... some override from another package
+
+# /etc/systemd/logind.conf.d/50-override.conf
+... some administrator override
+ </programlisting>
+ </example>
+
<para><command>systemd-analyze unit-paths</command> outputs a list of all
directories from which unit files, <filename>.d</filename> overrides, and
<filename>.wants</filename>, <filename>.requires</filename> symlinks may be
@@ -350,6 +355,13 @@
generators enabled will generally result in some warnings.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--root=<replaceable>PATH</replaceable></option></term>
+
+ <listitem><para>With <command>cat-files</command>, show config files underneath
+ the specified root path <replaceable>PATH</replaceable>.</para></listitem>
+ </varlistentry>
+
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="user-system-options.xml" xpointer="machine" />
diff --git a/man/systemd-ask-password-console.service.xml b/man/systemd-ask-password-console.service.xml
index db318de8c2..04f9596067 100644
--- a/man/systemd-ask-password-console.service.xml
+++ b/man/systemd-ask-password-console.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-ask-password-console.service">
<refentryinfo>
<title>systemd-ask-password-console.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>
diff --git a/man/systemd-ask-password.xml b/man/systemd-ask-password.xml
index 686fa89468..7ec76fabf0 100644
--- a/man/systemd-ask-password.xml
+++ b/man/systemd-ask-password.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-ask-password"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-ask-password</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -209,10 +183,10 @@
<varlistentry>
<term><option>--no-output</option></term>
- <listitem><para>Do not print passwords to standard output.
- This is useful if you want to store a password in kernel
- keyring with <option>--keyname</option> but do not want it
- to show up on screen or in logs.</para></listitem>
+ <listitem><para>Do not print passwords to standard output.
+ This is useful if you want to store a password in kernel
+ keyring with <option>--keyname</option> but do not want it
+ to show up on screen or in logs.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
diff --git a/man/systemd-backlight@.service.xml b/man/systemd-backlight@.service.xml
index e047884c50..a7865b20c2 100644
--- a/man/systemd-backlight@.service.xml
+++ b/man/systemd-backlight@.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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>
diff --git a/man/systemd-binfmt.service.xml b/man/systemd-binfmt.service.xml
index 0c33348ba8..c197b62847 100644
--- a/man/systemd-binfmt.service.xml
+++ b/man/systemd-binfmt.service.xml
@@ -3,38 +3,13 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="systemd-binfmt.service" conditional='ENABLE_BINFMT'>
+<refentry id="systemd-binfmt.service" conditional='ENABLE_BINFMT'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-binfmt.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>
@@ -65,6 +40,15 @@
for information about the configuration of this service.</para>
</refsect1>
+ <refsect1><title>Options</title>
+ <variablelist>
+ <xi:include href="standard-options.xml" xpointer="cat-config" />
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
+ <xi:include href="standard-options.xml" xpointer="help" />
+ <xi:include href="standard-options.xml" xpointer="version" />
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>See Also</title>
<para>
diff --git a/man/systemd-boot.xml b/man/systemd-boot.xml
new file mode 100644
index 0000000000..9fadffadfe
--- /dev/null
+++ b/man/systemd-boot.xml
@@ -0,0 +1,249 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="systemd-boot" conditional='ENABLE_EFI'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>systemd-boot</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-boot</refentrytitle>
+ <manvolnum>7</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-boot</refname>
+ <refname>sd-boot</refname>
+ <refpurpose>A simple UEFI boot manager</refpurpose>
+ </refnamediv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-boot</command> (short: <command>sd-boot</command>) is a simple UEFI boot manager. It
+ provides a graphical menu to select the entry to boot and an editor for the kernel command line. systemd-boot
+ supports systems with UEFI firmware only.</para>
+
+ <para>systemd-boot loads boot entry information from the EFI system partition (ESP), usually mounted at
+ <filename>/boot</filename>, <filename>/efi</filename>, or <filename>/boot/efi</filename> during OS
+ runtime. Configuration file fragments, kernels, initrds and other EFI images to boot generally need to reside on
+ the ESP. Linux kernels must be built with <option>CONFIG_EFI_STUB</option> to be able to be directly executed as an
+ EFI image. During boot systemd-boot automatically assembles a list of boot entries from the following
+ sources:</para>
+
+ <itemizedlist>
+ <listitem><para>Boot entries defined with <ulink
+ url="https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md">Boot Loader
+ Specification</ulink> description files located in <filename>/loader/entries/</filename> on the ESP. These
+ usually describe Linux kernel images with associated initrd images, but alternatively may also describe
+ arbitrary other EFI executables.</para></listitem>
+
+ <listitem><para>Unified kernel images following the <ulink
+ url="https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md">Boot Loader
+ Specification</ulink>, as executable EFI binaries in <filename>/EFI/Linux/</filename> on the ESP.
+ </para></listitem>
+
+ <listitem><para>The Microsoft Windows EFI boot manager, if installed</para></listitem>
+
+ <listitem><para>The Apple MacOS X boot manager, if installed</para></listitem>
+
+ <listitem><para>The EFI Shell binary, if installed</para></listitem>
+
+ <listitem><para>A reboot into the UEFI firmware setup option, if supported by the firmware</para></listitem>
+ </itemizedlist>
+
+ <para><citerefentry><refentrytitle>kernel-install</refentrytitle><manvolnum>8</manvolnum></citerefentry> may be
+ used to copy kernel images onto the ESP and to generate description files compliant with the Boot Loader
+ Specification. <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> may be
+ used from a running system to locate the ESP, list available entries, and install systemd-boot itself.</para>
+
+ <para>systemd-boot will provide information about the time spent in UEFI firmware using the <ulink
+ url="https://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface">Boot Loader Interface</ulink>. This
+ information can be displayed using
+ <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Key bindings</title>
+ <para>The following keys may be used in the boot menu:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>↑ (Up)</term>
+ <term>↓ (Down)</term>
+ <term>j</term>
+ <term>k</term>
+ <term>PageUp</term>
+ <term>PageDown</term>
+ <term>Home</term>
+ <term>End</term>
+ <listitem><para>Navigate up/down in the entry list</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>↵ (Enter)</term>
+ <listitem><para>Boot selected entry</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>d</term>
+ <listitem><para>Make selected entry the default</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>e</term>
+ <listitem><para>Edit the kernel command line for selected entry</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>+</term>
+ <term>t</term>
+ <listitem><para>Increase the timeout before default entry is booted</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-</term>
+ <term>T</term>
+ <listitem><para>Decrease the timeout</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>v</term>
+ <listitem><para>Show systemd-boot, UEFI, and firmware versions</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>P</term>
+ <listitem><para>Print status</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Q</term>
+ <listitem><para>Quit</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>h</term>
+ <term>?</term>
+ <listitem><para>Show a help screen</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Ctrl + l</term>
+ <listitem><para>Reprint the screen</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>The following keys may be used during bootup or in the boot menu to
+ directly boot a specific entry:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>l</term>
+ <listitem><para>Linux</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>w</term>
+ <listitem><para>Windows</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>a</term>
+ <listitem><para>OS X</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>s</term>
+ <listitem><para>EFI shell</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>1</term>
+ <term>2</term>
+ <term>3</term>
+ <term>4</term>
+ <term>5</term>
+ <term>6</term>
+ <term>7</term>
+ <term>8</term>
+ <term>9</term>
+ <listitem><para>Boot entry number 1 … 9</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>In the editor, most keys simply insert themselves, but the following keys
+ may be used to perform additional actions:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>← (Left)</term>
+ <term>→ (Right)</term>
+ <term>Home</term>
+ <term>End</term>
+ <listitem><para>Navigate left/right</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Esc</term>
+ <listitem><para>Abort the edit and quit the editor</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Ctrl + k</term>
+ <listitem><para>Clear the command line</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Ctrl + w</term>
+ <term>Alt + Backspace</term>
+ <listitem><para>Delete word backwards</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Alt + d </term>
+ <listitem><para>Delete word forwards</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>↵ (Enter)</term>
+ <listitem><para>Boot entry with the edited command line</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>Note that unless configured otherwise in the UEFI firmware, systemd-boot will
+ use the US keyboard layout, so key labels might not match for keys like +/-.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Files</title>
+
+ <para>The files systemd-boot reads generally reside on the UEFI ESP which is usually mounted to
+ <filename>/boot/</filename>, <filename>/efi/</filename> or <filename>/boot/efi</filename> during OS
+ runtime. systemd-boot reads runtime configuration such as the boot timeout and default entry from
+ <filename>/loader/loader.conf</filename> on the ESP (in combination with data read from EFI variables). See
+ <citerefentry><refentrytitle>loader.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Boot entry
+ description files following the <ulink
+ url="https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md">Boot Loader
+ Specification</ulink> are read from <filename>/loader/entries/</filename> on the ESP. Unified kernel boot entries
+ following the <ulink url="https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md">Boot
+ Loader Specification</ulink> are read from <filename>/EFI/Linux/</filename> on the ESP.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>loader.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <ulink url="https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md">Boot Loader Specification</ulink>,
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface">Boot Loader Interface</ulink>
+ </para>
+ </refsect1>
+</refentry>
diff --git a/man/systemd-cat.xml b/man/systemd-cat.xml
index 2c394f2ceb..72cd196c4e 100644
--- a/man/systemd-cat.xml
+++ b/man/systemd-cat.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-cat"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-cat</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-cgls.xml b/man/systemd-cgls.xml
index 128324e616..0d7f2b6481 100644
--- a/man/systemd-cgls.xml
+++ b/man/systemd-cgls.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-cgls"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-cgls</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-cgtop.xml b/man/systemd-cgtop.xml
index 295f235196..e5bd7a96e8 100644
--- a/man/systemd-cgtop.xml
+++ b/man/systemd-cgtop.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-cgtop"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-cgtop</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -159,8 +133,8 @@
<term><option>-r</option></term>
<term><option>--raw</option></term>
- <listitem><para>Format byte counts (as in memory usage and I/O metrics)
- with raw numeric values rather than human-readable
+ <listitem><para>Format byte counts (as in memory usage and I/O metrics)
+ with raw numeric values rather than human-readable
numbers.</para></listitem>
</varlistentry>
diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml
index 1ae9ffb89e..e011bf6b8b 100644
--- a/man/systemd-coredump.xml
+++ b/man/systemd-coredump.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-coredump" conditional='ENABLE_COREDUMP'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-coredump</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -141,6 +115,16 @@
core dumps and files can be set in files <filename>/etc/systemd/coredump.conf</filename> and snippets mentioned
above. In addition the storage time of core dump files is restricted by <command>systemd-tmpfiles</command>,
corresponding settings are by default in <filename>/usr/lib/tmpfiles.d/systemd.conf</filename>.</para>
+
+ <refsect2>
+ <title>Disabling coredump processing</title>
+
+ <para>To disable potentially resource-intensive processing by <command>systemd-coredump</command>,
+ set <programlisting>Storage=none
+ProcessSizeMax=0</programlisting> in
+ <citerefentry><refentrytitle>coredump.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd-cryptsetup-generator.xml b/man/systemd-cryptsetup-generator.xml
index 645e2ee178..c37ee76b87 100644
--- a/man/systemd-cryptsetup-generator.xml
+++ b/man/systemd-cryptsetup-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-cryptsetup-generator" conditional='HAVE_LIBCRYPTSETUP'>
<refentryinfo>
<title>systemd-cryptsetup-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>
diff --git a/man/systemd-cryptsetup@.service.xml b/man/systemd-cryptsetup@.service.xml
index efcbf247f4..439e8e9cd5 100644
--- a/man/systemd-cryptsetup@.service.xml
+++ b/man/systemd-cryptsetup@.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-cryptsetup@.service" conditional='HAVE_LIBCRYPTSETUP'>
<refentryinfo>
<title>systemd-cryptsetup@.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>
diff --git a/man/systemd-debug-generator.xml b/man/systemd-debug-generator.xml
index e8656a36ab..d5cf4109b0 100644
--- a/man/systemd-debug-generator.xml
+++ b/man/systemd-debug-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-debug-generator">
<refentryinfo>
<title>systemd-debug-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>
diff --git a/man/systemd-delta.xml b/man/systemd-delta.xml
index 94f6b093db..f86f2052fd 100644
--- a/man/systemd-delta.xml
+++ b/man/systemd-delta.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-delta"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-delta</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml
index 67b6c4fd32..54bba23666 100644
--- a/man/systemd-detect-virt.xml
+++ b/man/systemd-detect-virt.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-detect-virt"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-detect-virt</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -243,6 +217,12 @@
technology identifier.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--list</option></term>
+
+ <listitem><para>Output all currently known and detectable container and VM environments.</para></listitem>
+ </varlistentry>
+
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
diff --git a/man/systemd-environment-d-generator.xml b/man/systemd-environment-d-generator.xml
index 7bc1dd0ef1..44880e76e2 100644
--- a/man/systemd-environment-d-generator.xml
+++ b/man/systemd-environment-d-generator.xml
@@ -7,38 +7,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-environment-d-generator" conditional='ENABLE_ENVIRONMENT_D'>
<refentryinfo>
<title>systemd-environment-d-generator</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-escape.xml b/man/systemd-escape.xml
index 98cedef77d..41014abc73 100644
--- a/man/systemd-escape.xml
+++ b/man/systemd-escape.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-escape"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-escape</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml
index 0ac5f3bd85..a78e2d5067 100644
--- a/man/systemd-firstboot.xml
+++ b/man/systemd-firstboot.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-firstboot" conditional='ENABLE_FIRSTBOOT'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-firstboot</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-fsck@.service.xml b/man/systemd-fsck@.service.xml
index f4d2dc1341..e1996e4026 100644
--- a/man/systemd-fsck@.service.xml
+++ b/man/systemd-fsck@.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-fsck@.service">
<refentryinfo>
<title>systemd-fsck@.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>
@@ -78,7 +52,7 @@
<para><filename>systemd-fsck</filename> does not know any details
about specific filesystems, and simply executes file system
checkers specific to each filesystem type
- (<filename>/sbin/fsck.*</filename>). This helper will decide if
+ (<filename>/sbin/fsck.*</filename>). These checkers will decide if
the filesystem should actually be checked based on the time since
last check, number of mounts, unclean unmount, etc.</para>
diff --git a/man/systemd-fstab-generator.xml b/man/systemd-fstab-generator.xml
index 51e390a364..ab706420c5 100644
--- a/man/systemd-fstab-generator.xml
+++ b/man/systemd-fstab-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-fstab-generator">
<refentryinfo>
<title>systemd-fstab-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>
diff --git a/man/systemd-getty-generator.xml b/man/systemd-getty-generator.xml
index 17fd0e9c19..b5a300624f 100644
--- a/man/systemd-getty-generator.xml
+++ b/man/systemd-getty-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-getty-generator">
<refentryinfo>
<title>systemd-getty-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>
diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml
index 3fbe215c41..d98ef2003f 100644
--- a/man/systemd-gpt-auto-generator.xml
+++ b/man/systemd-gpt-auto-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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>
@@ -62,8 +36,9 @@
generator that automatically discovers root,
<filename>/home</filename>, <filename>/srv</filename> and swap
partitions and creates mount and swap units for them, based on the
- partition type GUIDs of GUID partition tables (GPT). It implements
- the <ulink
+ partition type GUIDs of GUID partition tables (GPT),
+ see <ulink url="http://www.uefi.org/specifications">UEFI Specification</ulink>, chapter 5.
+ It implements the <ulink
url="https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/">Discoverable
Partitions Specification</ulink>. Note that this generator has no
effect on non-GPT systems, or where the directories under the
@@ -78,13 +53,13 @@
same physical disk the EFI System Partition (ESP) is located on.
It will only look for the other partitions on the same physical
disk the root file system is located on. These partitions will not
- be searched on systems where the root file system is distributed
+ be searched for on systems where the root file system is distributed
on multiple disks, for example via btrfs RAID.</para>
<para><filename>systemd-gpt-auto-generator</filename> is useful
for centralizing file system configuration in the partition table
- and making manual configuration in <filename>/etc/fstab</filename>
- or suchlike unnecessary.</para>
+ and making configuration in <filename>/etc/fstab</filename> unnecessary.
+ </para>
<para>This generator looks for the partitions based on their
partition type GUID. The following partition type GUIDs are
@@ -153,6 +128,48 @@
</tgroup>
</table>
+ <para>This generator understands the following attribute flags for partitions:</para>
+
+ <table>
+ <title>Partition Attributes</title>
+ <tgroup cols='4' align='left' colsep='1' rowsep='1'>
+ <colspec colname="attribute" />
+ <colspec colname="value" />
+ <colspec colname="where" />
+ <colspec colname="explanation" />
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Value</entry>
+ <entry>Applicable to</entry>
+ <entry>Explanation</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><constant>GPT_FLAG_READ_ONLY</constant></entry>
+ <entry>0x1000000000000000</entry>
+ <entry><filename>/</filename>, <filename>/srv</filename>, <filename>/home</filename></entry>
+ <entry>Partition is mounted read-only</entry>
+ </row>
+
+ <row>
+ <entry><constant>GPT_FLAG_NO_AUTO</constant></entry>
+ <entry>0x8000000000000000</entry>
+ <entry><filename>/</filename>, <filename>/srv</filename>, <filename>/home</filename></entry>
+ <entry>Partition is not mounted automatically</entry>
+ </row>
+
+ <row>
+ <entry><constant>GPT_FLAG_NO_BLOCK_IO_PROTOCOL</constant></entry>
+ <entry>0x0000000000000002</entry>
+ <entry>ESP</entry>
+ <entry>Partition is not mounted automatically</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
<para>The <filename>/home</filename> and <filename>/srv</filename>
partitions may be encrypted in LUKS format. In this case, a device
mapper device is set up under the names
diff --git a/man/systemd-halt.service.xml b/man/systemd-halt.service.xml
index b58279d828..a40384ce56 100644
--- a/man/systemd-halt.service.xml
+++ b/man/systemd-halt.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-halt.service">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-halt.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>
@@ -114,7 +88,8 @@
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-hibernate-resume-generator.xml b/man/systemd-hibernate-resume-generator.xml
index 188bdb6e57..86d45dc4af 100644
--- a/man/systemd-hibernate-resume-generator.xml
+++ b/man/systemd-hibernate-resume-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Ivan Shapovalov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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-hibernate-resume-generator" conditional='ENABLE_HIBERNATE'>
<refentryinfo>
<title>systemd-hibernate-resume-generator</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Ivan</firstname>
- <surname>Shapovalov</surname>
- <email>intelfx100@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-hibernate-resume@.service.xml b/man/systemd-hibernate-resume@.service.xml
index cbda08961c..0db49e32ee 100644
--- a/man/systemd-hibernate-resume@.service.xml
+++ b/man/systemd-hibernate-resume@.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Ivan Shapovalov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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-hibernate-resume@.service" conditional='ENABLE_HIBERNATE'>
<refentryinfo>
<title>systemd-hibernate-resume@.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Ivan</firstname>
- <surname>Shapovalov</surname>
- <email>intelfx100@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-hostnamed.service.xml b/man/systemd-hostnamed.service.xml
index e905e461be..95c8bb6d30 100644
--- a/man/systemd-hostnamed.service.xml
+++ b/man/systemd-hostnamed.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-hostnamed.service" conditional='ENABLE_HOSTNAMED'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-hostnamed.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>
diff --git a/man/systemd-hwdb.xml b/man/systemd-hwdb.xml
index 58b151653b..5af868d52b 100644
--- a/man/systemd-hwdb.xml
+++ b/man/systemd-hwdb.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-hwdb" conditional="ENABLE_HWDB"
@@ -29,20 +12,6 @@
<refentryinfo>
<title>systemd-hwdb</title>
<productname>systemd</productname>
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -83,6 +52,13 @@
<para>Alternate root path in the filesystem.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-s</option></term>
+ <term><option>--strict</option></term>
+ <listitem>
+ <para>When updating, return non-zero exit value on any parsing error.</para>
+ </listitem>
+ </varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
diff --git a/man/systemd-importd.service.xml b/man/systemd-importd.service.xml
index 9fd36bb3b3..ec967c4718 100644
--- a/man/systemd-importd.service.xml
+++ b/man/systemd-importd.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-importd.service" conditional='ENABLE_IMPORTD'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-importd.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>
diff --git a/man/systemd-inhibit.xml b/man/systemd-inhibit.xml
index ce34cc8c50..03dc06678a 100644
--- a/man/systemd-inhibit.xml
+++ b/man/systemd-inhibit.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-inhibit"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-inhibit</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -144,6 +118,7 @@
acquiring one.</para></listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
@@ -168,6 +143,8 @@
doing so.</para>
</refsect1>
+ <xi:include href="less-variables.xml" />
+
<refsect1>
<title>See Also</title>
<para>
diff --git a/man/systemd-initctl.service.xml b/man/systemd-initctl.service.xml
index 64211e27f7..f9627c9294 100644
--- a/man/systemd-initctl.service.xml
+++ b/man/systemd-initctl.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-initctl.service">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-initctl.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>
diff --git a/man/systemd-journal-gatewayd.service.xml b/man/systemd-journal-gatewayd.service.xml
index dbc859285b..794bc10a7b 100644
--- a/man/systemd-journal-gatewayd.service.xml
+++ b/man/systemd-journal-gatewayd.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-journal-gatewayd.service" conditional='HAVE_MICROHTTPD'
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-journal-gatewayd.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -313,8 +287,10 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-journal-remote.xml b/man/systemd-journal-remote.service.xml
index 658c7e07f4..f2bfc36668 100644
--- a/man/systemd-journal-remote.xml
+++ b/man/systemd-journal-remote.service.xml
@@ -7,55 +7,33 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-journal-remote" conditional='HAVE_MICROHTTPD'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
- <title>systemd-journal-remote</title>
+ <title>systemd-journal-remote.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
- <refentrytitle>systemd-journal-remote</refentrytitle>
+ <refentrytitle>systemd-journal-remote.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
+ <refname>systemd-journal-remote.service</refname>
+ <refname>systemd-journal-remote.socket</refname>
<refname>systemd-journal-remote</refname>
<refpurpose>Receive journal messages over the network</refpurpose>
</refnamediv>
<refsynopsisdiv>
+ <para><filename>systemd-journal-remote.service</filename></para>
+ <para><filename>systemd-journal-remote.socket</filename></para>
<cmdsynopsis>
- <command>systemd-journal-remote</command>
+ <command>/usr/lib/systemd/systemd-journal-remote</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="opt" rep="norepeat">-o/--output=<replaceable>DIR</replaceable>|<replaceable>FILE</replaceable></arg>
<arg choice="opt" rep="repeat">SOURCES</arg>
@@ -65,18 +43,19 @@
<refsect1>
<title>Description</title>
- <para>
- <filename>systemd-journal-remote</filename> is a command to
- receive serialized journal events and store them to the journal.
- Input streams are in the
- <ulink url="https://www.freedesktop.org/wiki/Software/systemd/export">
- Journal Export Format
- </ulink>,
- i.e. like the output from
- <command>journalctl --output=export</command>. For transport over
- the network, this serialized stream is usually carried over an
- HTTPS connection.
- </para>
+ <para><command>systemd-journal-remote</command> is a command to receive serialized journal
+ events and store them to journal files. Input streams are in the
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/export">Journal Export Format</ulink>,
+ i.e. like the output from <command>journalctl --output=export</command>. For transport over the
+ network, this serialized stream is usually carried over an HTTPS connection.</para>
+
+ <para><filename>systemd-journal-remote.service</filename> is a system service that uses
+ <command>systemd-journal-remote</command> to listen for connections.
+ <filename>systemd-journal-remote.socket</filename> configures the network address that
+ <filename>systemd-journal-remote.service</filename> listens on. By default this is port 19532.
+ What connections are accepted and how the received data is stored can be configured through the
+ <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ configuration file.</para>
</refsect1>
<refsect1>
@@ -172,12 +151,12 @@
interpreted as the (negated) file descriptor number, or an
address suitable for <option>ListenStream=</option> (c.f.
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
- In the first case, matching file descriptor must be inherited
- through
+ In the first case, the server listens on port 19532 by default,
+ and the matching file descriptor must be inherited through
<varname>$LISTEN_FDS</varname>/<varname>$LISTEN_PID</varname>.
In the second case, an HTTP or HTTPS server will be spawned on
- this port, respectively for <option>--listen-http</option> and
- <option>--listen-https</option>. Currently, only POST requests
+ this port, respectively for <option>--listen-http=</option> and
+ <option>--listen-https=</option>. Currently, only POST requests
to <filename>/upload</filename> with <literal>Content-Type:
application/vnd.fdo.journal</literal> are supported.</para>
</listitem>
@@ -364,11 +343,11 @@ systemd-journal-remote --url http://some.host:19531/entries?boot&amp;follow
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>
diff --git a/man/systemd-journal-upload.xml b/man/systemd-journal-upload.service.xml
index fecffd5d9b..38fc010ab6 100644
--- a/man/systemd-journal-upload.xml
+++ b/man/systemd-journal-upload.service.xml
@@ -7,55 +7,31 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-journal-upload" conditional='HAVE_MICROHTTPD'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
- <title>systemd-journal-upload</title>
+ <title>systemd-journal-upload.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
- <refentrytitle>systemd-journal-upload</refentrytitle>
+ <refentrytitle>systemd-journal-upload.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
+ <refname>systemd-journal-upload.service</refname>
<refname>systemd-journal-upload</refname>
<refpurpose>Send journal messages over the network</refpurpose>
</refnamediv>
<refsynopsisdiv>
+ <para><filename>systemd-journal-upload.service</filename></para>
<cmdsynopsis>
- <command>systemd-journal-upload</command>
+ <command>/usr/lib/systemd/systemd-journal-upload</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="opt" rep="norepeat">-u/--url=<replaceable>URL</replaceable></arg>
<arg choice="opt" rep="repeat">SOURCES</arg>
@@ -65,14 +41,19 @@
<refsect1>
<title>Description</title>
- <para>
- <command>systemd-journal-upload</command> will upload journal
- entries to the URL specified with <option>--url</option>. Unless
- limited by one of the options specified below, all journal
- entries accessible to the user the program is running as will be
- uploaded, and then the program will wait and send new entries
- as they become available.
- </para>
+ <para><command>systemd-journal-upload</command> will upload journal entries to the URL specified
+ with <option>--url=</option>. This program reads journal entries from one or more journal files,
+ similarly to
+ <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ Unless limited by one of the options specified below, all journal entries accessible to the user
+ the program is running as will be uploaded, and then the program will wait and send new entries
+ as they become available.</para>
+
+ <para><filename>systemd-journal-upload.service</filename> is a system service that uses
+ <command>systemd-journal-upload</command> to upload journal entries to a server. It uses the
+ configuration in
+ <citerefentry><refentrytitle>journal-upload.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ At least the <varname>URL=</varname> option must be specified.</para>
</refsect1>
<refsect1>
@@ -81,13 +62,15 @@
<variablelist>
<varlistentry>
<term><option>-u</option></term>
- <term><option>--url=<optional>https://</optional><replaceable>URL</replaceable></option></term>
- <term><option>--url=<optional>http://</optional><replaceable>URL</replaceable></option></term>
+ <term><option>--url=<optional>https://</optional><replaceable>URL</replaceable>[:<replaceable>PORT</replaceable>]</option></term>
+ <term><option>--url=<optional>http://</optional><replaceable>URL</replaceable>[:<replaceable>PORT</replaceable>]</option></term>
<listitem><para>Upload to the specified
address. <replaceable>URL</replaceable> may specify either
just the hostname or both the protocol and
hostname. <constant>https</constant> is the default.
+ The port number may be specified after a colon (<literal>:</literal>),
+ otherwise <constant>19532</constant> will be used by default.
</para></listitem>
</varlistentry>
@@ -123,7 +106,7 @@
entries from the specified journal directory
<replaceable>DIR</replaceable> instead of the default runtime
and system journal paths. This has the same meaning as
- <option>--directory</option> option for
+ <option>--directory=</option> option for
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
@@ -136,7 +119,7 @@
<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. This has the same meaning as
- <option>--file</option> option for
+ <option>--file=</option> option for
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
@@ -146,7 +129,7 @@
<listitem><para>Upload entries from the location in the
journal specified by the passed cursor. This has the same
- meaning as <option>--cursor</option> option for
+ meaning as <option>--cursor=</option> option for
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
@@ -156,12 +139,11 @@
<listitem><para>Upload entries from the location in the
journal <emphasis>after</emphasis> the location specified by
the this cursor. This has the same meaning as
- <option>--after-cursor</option> option for
+ <option>--after-cursor=</option> option for
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
-
<varlistentry>
<term><option>--save-state</option><optional>=<replaceable>PATH</replaceable></optional></term>
@@ -233,7 +215,8 @@
legitimate, and vice versa, that the client is trusted.</para>
<para>A suitable set of certificates can be generated with
- <command>openssl</command>:</para>
+ <command>openssl</command>. Note, 2048 bits of key length
+ is minimally recommended to use for security reasons:</para>
<programlisting>openssl req -newkey rsa:2048 -days 3650 -x509 -nodes \
-out ca.pem -keyout ca.key -subj '/CN=Certificate authority/'
@@ -296,7 +279,8 @@ openssl ca -batch -config ca.conf -notext -in $CLIENT.csr -out $CLIENT.pem
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journal-upload.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
diff --git a/man/systemd-journald.service.xml b/man/systemd-journald.service.xml
index 8ca0e896ab..6d0aaa4587 100644
--- a/man/systemd-journald.service.xml
+++ b/man/systemd-journald.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-journald.service">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-journald.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>
@@ -261,9 +235,7 @@ systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
<varlistentry>
<term><filename>/etc/systemd/journald.conf</filename></term>
- <listitem><para>Configure
- <command>systemd-journald</command>
- behavior. See
+ <listitem><para>Configure <command>systemd-journald</command> behavior. See
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
@@ -274,8 +246,7 @@ systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
<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
+ <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>
@@ -287,7 +258,24 @@ systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
<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>
+ configuration file.</para>
+
+ <para>When <filename>systemd-journald</filename> ceases writing to a journal file,
+ it will be renamed to <literal><replaceable>original-name</replaceable>@<replaceable>suffix.journal</replaceable></literal>
+ (or <literal><replaceable>original-name</replaceable>@<replaceable>suffix.journal~</replaceable></literal>).
+ Such files are "archived" and will not be written to any more.</para>
+
+ <para>In general, it is safe to read or copy any journal file (active or archived).
+ <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ and the functions in the
+ <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ library should be able to read all entries that have been fully written.</para>
+
+ <para><filename>systemd-journald</filename> will automatically remove the oldest
+ archived journal files to limit disk use. See <varname>SystemMaxUse=</varname>
+ and related settings in
+ <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd-localed.service.xml b/man/systemd-localed.service.xml
index 308a848c08..baf20c05db 100644
--- a/man/systemd-localed.service.xml
+++ b/man/systemd-localed.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-localed.service" conditional='ENABLE_LOCALED'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-localed.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>
diff --git a/man/systemd-logind.service.xml b/man/systemd-logind.service.xml
index f3a3b24200..33ed8f522e 100644
--- a/man/systemd-logind.service.xml
+++ b/man/systemd-logind.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-logind.service" conditional='ENABLE_LOGIND'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-logind.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>
diff --git a/man/systemd-machine-id-commit.service.xml b/man/systemd-machine-id-commit.service.xml
index acb4ffb626..06e70fc297 100644
--- a/man/systemd-machine-id-commit.service.xml
+++ b/man/systemd-machine-id-commit.service.xml
@@ -4,37 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2014 Didier Roche
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Didier Roche
-->
<refentry id="systemd-machine-id-commit.service">
<refentryinfo>
<title>systemd-machine-id-commit.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Didier</firstname>
- <surname>Roche</surname>
- <email>didrocks@ubuntu.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-machine-id-setup.xml b/man/systemd-machine-id-setup.xml
index 8c4a62ccee..7f0dcd14d7 100644
--- a/man/systemd-machine-id-setup.xml
+++ b/man/systemd-machine-id-setup.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-machine-id-setup"
@@ -29,21 +12,6 @@
<refentryinfo>
<title>systemd-machine-id-setup</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- <author>
- <contrib>Developer</contrib>
- <firstname>Didier</firstname>
- <surname>Roche</surname>
- <email>didrocks@ubuntu.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-machined.service.xml b/man/systemd-machined.service.xml
index 8bf4e75550..b5f3bc2864 100644
--- a/man/systemd-machined.service.xml
+++ b/man/systemd-machined.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-machined.service" conditional='ENABLE_MACHINED'>
@@ -28,15 +11,6 @@
<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>
diff --git a/man/systemd-makefs@.service.xml b/man/systemd-makefs@.service.xml
index 073c52fafe..c8e201eb86 100644
--- a/man/systemd-makefs@.service.xml
+++ b/man/systemd-makefs@.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-makefs@.service">
<refentryinfo>
<title>systemd-makefs@.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -69,7 +43,7 @@
in <citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
see <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
They are instantiated for each device for which the file system or swap structure
- needs to be initalized, and for each mount point where the file system needs to
+ needs to be initialized, and for each mount point where the file system needs to
be grown.</para>
<para>These services are started at boot, either right before or right after the
diff --git a/man/systemd-modules-load.service.xml b/man/systemd-modules-load.service.xml
index 6f370190f2..5aa70b709a 100644
--- a/man/systemd-modules-load.service.xml
+++ b/man/systemd-modules-load.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-modules-load.service" conditional='HAVE_KMOD'>
<refentryinfo>
<title>systemd-modules-load.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>
diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml
index 76ea0550d7..c75e572026 100644
--- a/man/systemd-mount.xml
+++ b/man/systemd-mount.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-mount"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-mount</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -282,7 +256,7 @@
all mount units that mount and failed are kept in memory until the user explicitly resets their failure state with
<command>systemctl reset-failed</command> or an equivalent command. On the other hand, units that stopped
successfully are unloaded immediately. If this option is turned on the "garbage collection" of units is more
- agressive, and unloads units regardless if they exited successfully or failed. This option is a shortcut for
+ aggressive, and unloads units regardless if they exited successfully or failed. This option is a shortcut for
<command>--property=CollectMode=inactive-or-failed</command>, see the explanation for
<varname>CollectMode=</varname> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for further
diff --git a/man/systemd-networkd-wait-online.service.xml b/man/systemd-networkd-wait-online.service.xml
index 7cec7da9d7..95abf5b873 100644
--- a/man/systemd-networkd-wait-online.service.xml
+++ b/man/systemd-networkd-wait-online.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-networkd-wait-online.service" conditional='ENABLE_NETWORKD'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-networkd-wait-online.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -59,7 +33,7 @@
<title>Description</title>
<para><command>systemd-networkd-wait-online</command> is a
- one-shot system service that waits for the network to be
+ oneshot system service (see <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>), that waits for the network to be
configured. By default, it will wait for all links it is aware of
and which are managed by
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
@@ -105,6 +79,7 @@
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-networkd.service.xml b/man/systemd-networkd.service.xml
index 8bc5f5e869..bac43667b9 100644
--- a/man/systemd-networkd.service.xml
+++ b/man/systemd-networkd.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-networkd.service" conditional='ENABLE_NETWORKD'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-networkd.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-notify.xml b/man/systemd-notify.xml
index 874bdd882b..18d87329ab 100644
--- a/man/systemd-notify.xml
+++ b/man/systemd-notify.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-notify"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-notify</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index b8b3d045eb..7b3d211161 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -1,26 +1,12 @@
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
+<!ENTITY blag_latest_version "140">
+<!ENTITY fedora_cloud_release "1.1">
+]>
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-nspawn"
@@ -29,15 +15,6 @@
<refentryinfo>
<title>systemd-nspawn</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -387,6 +364,22 @@
</varlistentry>
<varlistentry>
+ <term><option>--hostname=</option></term>
+
+ <listitem><para>Controls the hostname to set within the container, if different from the machine name. Expects
+ a valid hostname as argument. If this option is used, the kernel hostname of the container will be set to this
+ value, otherwise it will be initialized to the machine name as controlled by the <option>--machine=</option>
+ option described above. The machine name is used for various aspect of identification of the container from the
+ outside, the kernel hostname configurable with this option is useful for the container to identify itself from
+ the inside. It is usually a good idea to keep both forms of identification synchronized, in order to avoid
+ confusion. It is hence recommended to avoid usage of this option, and use <option>--machine=</option>
+ exclusively. Note that regardless whether the container's hostname is initialized from the name set with
+ <option>--hostname=</option> or the one set with <option>--machine=</option>, the container can later override
+ its kernel hostname freely on its own as well.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--uuid=</option></term>
<listitem><para>Set the specified UUID for the container. The
@@ -731,12 +724,23 @@
</varlistentry>
<varlistentry>
+ <term><option>--no-new-privileges=</option></term>
+
+ <listitem><para>Takes a boolean argument. Specifies the value of the <constant>PR_SET_NO_NEW_PRIVS</constant>
+ flag for the container payload. Defaults to off. When turned on the payload code of the container cannot
+ acquire new privileges, i.e. the "setuid" file bit as well as file system capabilities will not have an effect
+ anymore. See <citerefentry
+ project='man-pages'><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry> for details
+ about this flag. </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--system-call-filter=</option></term>
<listitem><para>Alter the system call filter applied to containers. Takes a space-separated list of system call
names or group names (the latter prefixed with <literal>@</literal>, as listed by the
- <command>syscall-filter</command> command of <citerefentry
- project='man-pages'><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>). Passed
+ <command>syscall-filter</command> command of
+ <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>). Passed
system calls will be permitted. The list may optionally be prefixed by <literal>~</literal>, in which case all
listed system calls are prohibited. If this command line option is used multiple times the configured lists are
combined. If both a positive and a negative list (that is one system call list without and one with the
@@ -748,15 +752,59 @@
</varlistentry>
<varlistentry>
+ <term><option>--rlimit=</option></term>
+
+ <listitem><para>Sets the specified POSIX resource limit for the container payload. Expects an assignment of the
+ form
+ <literal><replaceable>LIMIT</replaceable>=<replaceable>SOFT</replaceable>:<replaceable>HARD</replaceable></literal>
+ or <literal><replaceable>LIMIT</replaceable>=<replaceable>VALUE</replaceable></literal>, where
+ <replaceable>LIMIT</replaceable> should refer to a resource limit type, such as
+ <constant>RLIMIT_NOFILE</constant> or <constant>RLIMIT_NICE</constant>. The <replaceable>SOFT</replaceable> and
+ <replaceable>HARD</replaceable> fields should refer to the numeric soft and hard resource limit values. If the
+ second form is used, <replaceable>VALUE</replaceable> may specify a value that is used both as soft and hard
+ limit. In place of a numeric value the special string <literal>infinity</literal> may be used to turn off
+ resource limiting for the specific type of resource. This command line option may be used multiple times to
+ control limits on multiple limit types. If used multiple times for the same limit type, the last use
+ wins. For details about resource limits see <citerefentry
+ project='man-pages'><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>. By default
+ resource limits for the container's init process (PID 1) are set to the same values the Linux kernel originally
+ passed to the host init system. Note that some resource limits are enforced on resources counted per user, in
+ particular <constant>RLIMIT_NPROC</constant>. This means that unless user namespacing is deployed
+ (i.e. <option>--private-users=</option> is used, see above), any limits set will be applied to the resource
+ usage of the same user on all local containers as well as the host. This means particular care needs to be
+ taken with these limits as they might be triggered by possibly less trusted code. Example:
+ <literal>--rlimit=RLIMIT_NOFILE=8192:16384</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--oom-score-adjust=</option></term>
+
+ <listitem><para>Changes the OOM ("Out Of Memory") score adjustment value for the container payload. This controls
+ <filename>/proc/self/oom_score_adj</filename> which influences the preference with which this container is
+ terminated when memory becomes scarce. For details see <citerefentry
+ project='man-pages'><refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Takes an
+ integer in the range -1000…1000.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--cpu-affinity=</option></term>
+
+ <listitem><para>Controls the CPU affinity of the container payload. Takes a comma separated list of CPU numbers
+ or number ranges (the latter's start and end value separated by dashes). See <citerefentry
+ project='man-pages'><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--kill-signal=</option></term>
- <listitem><para>Specify the process signal to send to the
- container's PID 1 when nspawn itself receives SIGTERM, in
- order to trigger an orderly shutdown of the
- container. Defaults to SIGRTMIN+3 if <option>--boot</option>
- is used (on systemd-compatible init systems SIGRTMIN+3
- triggers an orderly shutdown). For a list of valid signals, see
- <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem>
+ <listitem><para>Specify the process signal to send to the container's PID 1 when nspawn itself receives
+ <constant>SIGTERM</constant>, in order to trigger an orderly shutdown of the container. Defaults to
+ <constant>SIGRTMIN+3</constant> if <option>--boot</option> is used (on systemd-compatible init systems
+ <constant>SIGRTMIN+3</constant> triggers an orderly shutdown). If <option>--boot</option> is not used and this
+ option is not specified the container's processes are terminated abrubtly via <constant>SIGKILL</constant>. For
+ a list of valid signals, see <citerefentry
+ project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
@@ -801,6 +849,54 @@
</varlistentry>
<varlistentry>
+ <term><option>--resolv-conf=</option></term>
+
+ <listitem><para>Configures how <filename>/etc/resolv.conf</filename> inside of the container (i.e. DNS
+ configuration synchronization from host to container) shall be handled. Takes one of <literal>off</literal>,
+ <literal>copy-host</literal>, <literal>copy-static</literal>, <literal>bind-host</literal>,
+ <literal>bind-static</literal>, <literal>delete</literal> or <literal>auto</literal>. If set to
+ <literal>off</literal> the <filename>/etc/resolv.conf</filename> file in the container is left as it is
+ included in the image, and neither modified nor bind mounted over. If set to <literal>copy-host</literal>, the
+ <filename>/etc/resolv.conf</filename> file from the host is copied into the container. Similar, if
+ <literal>bind-host</literal> is used, the file is bind mounted from the host into the container. If set to
+ <literal>copy-static</literal> the static <filename>resolv.conf</filename> file supplied with
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> is
+ copied into the container, and correspondingly <literal>bind-static</literal> bind mounts it there. If set to
+ <literal>delete</literal> the <filename>/etc/resolv.conf</filename> file in the container is deleted if it
+ exists. Finally, if set to <literal>auto</literal> the file is left as it is if private networking is turned on
+ (see <option>--private-network</option>). Otherwise, if <filename>systemd-resolved.service</filename> is
+ connectible its static <filename>resolv.conf</filename> file is used, and if not the host's
+ <filename>/etc/resolv.conf</filename> file is used. In the latter cases the file is copied if the image is
+ writable, and bind mounted otherwise. It's recommended to use <literal>copy</literal> if the container shall be
+ able to make changes to the DNS configuration on its own, deviating from the host's settings. Otherwise
+ <literal>bind</literal> is preferable, as it means direct changes to <filename>/etc/resolv.conf</filename> in
+ the container are not allowed, as it is a read-only bind mount (but note that if the container has enough
+ privileges, it might simply go ahead and unmount the bind mount anyway). Note that both if the file is bind
+ mounted and if it is copied no further propagation of configuration is generally done after the one-time early
+ initialization (this is because the file is usually updated through copying and renaming). Defaults to
+ <literal>auto</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--timezone=</option></term>
+
+ <listitem><para>Configures how <filename>/etc/localtime</filename> inside of the container (i.e. local timezone
+ synchronization from host to container) shall be handled. Takes one of <literal>off</literal>,
+ <literal>copy</literal>, <literal>bind</literal>, <literal>symlink</literal>, <literal>delete</literal> or
+ <literal>auto</literal>. If set to <literal>off</literal> the <filename>/etc/localtime</filename> file in the
+ container is left as it is included in the image, and neither modified nor bind mounted over. If set to
+ <literal>copy</literal> the <filename>/etc/localtime</filename> file of the host is copied into the
+ container. Similar, if <literal>bind</literal> is used, it is bind mounted from the host into the container. If
+ set to <literal>symlink</literal> a symlink from <filename>/etc/localtime</filename> in the container is
+ created pointing to the matching the timezone file of the container that matches the timezone setting on the
+ host. If set to <literal>delete</literal> the file in the container is deleted, should it exist. If set to
+ <literal>auto</literal> and the <filename>/etc/localtime</filename> file of the host is a symlink, then
+ <literal>symlink</literal> mode is used, and <literal>copy</literal> otherwise, except if the image is
+ read-only in which case <literal>bind</literal> is used instead. Defaults to
+ <literal>auto</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--read-only</option></term>
<listitem><para>Mount the root file system read-only for the
@@ -1086,8 +1182,8 @@
<ulink url="https://getfedora.org">Fedora</ulink> image and start a shell in it</title>
<programlisting># machinectl pull-raw -&2D;verify=no \
- https://download.fedoraproject.org/pub/fedora/linux/releases/25/CloudImages/x86_64/images/Fedora-Cloud-Base-25-1.3.x86_64.raw.xz
-# systemd-nspawn -M Fedora-Cloud-Base-25-1.3.x86_64.raw</programlisting>
+ https://download.fedoraproject.org/pub/fedora/linux/releases/&fedora_latest_version;/Cloud/x86_64/images/Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64.raw.xz
+# systemd-nspawn -M Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64.raw</programlisting>
<para>This downloads an image using
<citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
@@ -1098,17 +1194,17 @@
<example>
<title>Build and boot a minimal BLAG distribution in a container</title>
- <programlisting># dnf -y --releasever=140k --installroot=/var/lib/machines/blag140container \
+ <programlisting># dnf -y --releasever=&blag_latest_version;k --installroot=/var/lib/machines/blag&blag_latest_version; \
--disablerepo='*' --enablerepo=blag --enablerepo=updates install \
systemd passwd dnf blag-release vim-minimal
-# systemd-nspawn -bD /var/lib/machines/blag140container</programlisting>
+# systemd-nspawn -bD /var/lib/machines/blag&blag_latest_version;</programlisting>
<para>This installs a minimal BLAG distribution into the
- directory <filename noindex='true'>/var/lib/machines/blag140container</filename>
+ directory <filename noindex='true'>/var/lib/machines/blag&blag_latest_version;</filename>
and then boots an OS in a namespace container in it. Because the installation
is located underneath the standard <filename>/var/lib/machines/</filename>
directory, it is also possible to start the machine using
- <command>systemd-nspawn -M blag140container</command>.</para>
+ <command>systemd-nspawn -M blag&blag_latest_version;</command>.</para>
</example>
<example>
diff --git a/man/systemd-path.xml b/man/systemd-path.xml
index 7144569d59..b610af672b 100644
--- a/man/systemd-path.xml
+++ b/man/systemd-path.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-path"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-path</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -52,7 +26,9 @@
<refsynopsisdiv>
<cmdsynopsis>
- <command>systemd-path <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt" rep="repeat">NAME</arg></command>
+ <command>systemd-path</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="opt" rep="repeat">NAME</arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -81,8 +57,7 @@
<varlistentry>
<term><option>--suffix=</option></term>
- <listitem><para>The printed paths are suffixed by the
- specified string.</para></listitem>
+ <listitem><para>Printed paths are suffixed by the specified string.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
diff --git a/man/systemd-portabled.service.xml b/man/systemd-portabled.service.xml
new file mode 100644
index 0000000000..a6bd6c52e7
--- /dev/null
+++ b/man/systemd-portabled.service.xml
@@ -0,0 +1,51 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="systemd-portabled.service" conditional='ENABLE_PORTABLED'>
+
+ <refentryinfo>
+ <title>systemd-portabled.service</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-portabled.service</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-portabled.service</refname>
+ <refname>systemd-portabled</refname>
+ <refpurpose>Portable service manager</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>systemd-portabled.service</filename></para>
+ <para><filename>/usr/lib/systemd/systemd-portabled</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-portabled</command> is a system service that may be used to attach, detach and inspect
+ portable service images.</para>
+
+ <para>Most of <command>systemd-portabled</command>'s functionality is accessible through the
+ <citerefentry><refentrytitle>portablectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> command.</para>
+
+ <para>See the <ulink url="https://github.com/systemd/systemd/blob/master/doc/PORTABLE_SERVICES.md">Portable
+ Services Documentation</ulink> for details about the concepts this service implements.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>portablectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd-quotacheck.service.xml b/man/systemd-quotacheck.service.xml
index c3a5e69d40..c7cf23779a 100644
--- a/man/systemd-quotacheck.service.xml
+++ b/man/systemd-quotacheck.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-quotacheck.service" conditional='ENABLE_QUOTACHECK'>
<refentryinfo>
<title>systemd-quotacheck.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>
diff --git a/man/systemd-random-seed.service.xml b/man/systemd-random-seed.service.xml
index 658bdf3638..dc5c884404 100644
--- a/man/systemd-random-seed.service.xml
+++ b/man/systemd-random-seed.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-random-seed.service" conditional='ENABLE_RANDOMSEED'>
<refentryinfo>
<title>systemd-random-seed.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>
diff --git a/man/systemd-rc-local-generator.xml b/man/systemd-rc-local-generator.xml
index 89cd7ec614..3474a8f1d7 100644
--- a/man/systemd-rc-local-generator.xml
+++ b/man/systemd-rc-local-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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-rc-local-generator">
<refentryinfo>
<title>systemd-rc-local-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>
diff --git a/man/systemd-remount-fs.service.xml b/man/systemd-remount-fs.service.xml
index 8e68b99fe5..988a617406 100644
--- a/man/systemd-remount-fs.service.xml
+++ b/man/systemd-remount-fs.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-remount-fs.service">
<refentryinfo>
<title>systemd-remount-fs.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>
diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml
index 3a629b09ec..d2dc0538ca 100644
--- a/man/systemd-resolved.service.xml
+++ b/man/systemd-resolved.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-resolved.service" conditional='ENABLE_RESOLVE'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-resolved.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -59,8 +33,8 @@
<title>Description</title>
<para><command>systemd-resolved</command> is a system service that provides network name resolution to local
- applications. It implements a caching and validating DNS/DNSSEC stub resolver, as well as an LLMNR resolver and
- responder. Local applications may submit network name resolution requests via three interfaces:</para>
+ applications. It implements a caching and validating DNS/DNSSEC stub resolver, as well as an LLMNR and MulticastDNS
+ resolver and responder. Local applications may submit network name resolution requests via three interfaces:</para>
<itemizedlist>
<listitem><para>The native, fully-featured API <command>systemd-resolved</command> exposes on the bus. See the
@@ -90,8 +64,10 @@
<para>The DNS servers contacted are determined from the global settings in
<filename>/etc/systemd/resolved.conf</filename>, the per-link static settings in
- <filename>/etc/systemd/network/*.network</filename> files, the per-link dynamic settings received over DHCP and any
- DNS server information made available by other system services. See
+ <filename>/etc/systemd/network/*.network</filename> files (in case
+ <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> is
+ used), the per-link dynamic settings received over DHCP, and any DNS server information made available by other
+ system services. See
<citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> and
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details
about systemd's own configuration files for DNS servers. To improve compatibility,
@@ -124,27 +100,31 @@
non-address types (like MX).</para></listitem>
</itemizedlist>
- <para>Lookup requests are routed to the available DNS servers
- and LLMNR interfaces according to the following rules:</para>
+ <para>Lookup requests are routed to the available DNS servers, LLMNR and MulticastDNS interfaces according to the
+ following rules:</para>
<itemizedlist>
- <listitem><para>Lookups for the special hostname
- <literal>localhost</literal> are never routed to the
- network. (A few other, special domains are handled the same way.)</para></listitem>
-
- <listitem><para>Single-label names are routed to all local
- interfaces capable of IP multicasting, using the LLMNR
- protocol. Lookups for IPv4 addresses are only sent via LLMNR on
- IPv4, and lookups for IPv6 addresses are only sent via LLMNR on
- IPv6. Lookups for the locally configured host name and the
- <literal>_gateway</literal> host name are never routed to
- LLMNR.</para></listitem>
-
- <listitem><para>Multi-label names are routed to all local
- interfaces that have a DNS server configured, plus the globally
- configured DNS server if there is one. Address lookups from the
- link-local address range are never routed to
- DNS.</para></listitem>
+ <listitem><para>Lookups for the special hostname <literal>localhost</literal> are never routed to the network. (A
+ few other, special domains are handled the same way.)</para></listitem>
+
+ <listitem><para>Single-label names are routed to all local interfaces capable of IP multicasting, using the LLMNR
+ protocol. Lookups for IPv4 addresses are only sent via LLMNR on IPv4, and lookups for IPv6 addresses are only
+ sent via LLMNR on IPv6. Lookups for the locally configured host name and the <literal>_gateway</literal> host
+ name are never routed to LLMNR.</para></listitem>
+
+ <listitem><para>Multi-label names with the domain suffix <literal>.local</literal> are routed to all local
+ interfaces capable of IP multicasting, using the MulticastDNS protocol. As with LLMNR IPv4 address lookups are
+ sent via IPv4 and IPv6 address lookups are sent via IPv6.</para></listitem>
+
+ <listitem><para>Other multi-label names are routed to all local interfaces that have a DNS server configured,
+ plus the globally configured DNS server if there is one. Address lookups from the link-local address range are
+ never routed to DNS. Note that by default lookups for domains with the <literal>.local</literal> suffix are not
+ routed to DNS servers, unless the domain is specified explicitly as routing or search domain for the DNS server
+ and interface. This means that on networks where the <literal>.local</literal> domain is defined in a
+ site-specific DNS server, explicit search or routing domains need to be configured to make lookups within this
+ DNS domain work. Note that today it's generally recommended to avoid defining <literal>.local</literal> in a DNS
+ server, as <ulink url="https://tools.ietf.org/html/rfc6762">RFC6762</ulink> reserves this domain for exclusive
+ MulticastDNS use.</para></listitem>
</itemizedlist>
<para>If lookups are routed to multiple interfaces, the first
@@ -229,7 +209,7 @@
<command>systemd-resolved</command> will flush all caches it maintains. Note that it should normally not be
necessary to request this explicitly – except for debugging purposes – as <command>systemd-resolved</command>
flushes the caches automatically anyway any time the host's network configuration changes. Sending this signal
- to <command>systemd-resolved</command> is equivalent to the <command>systemd-resolve --flush-caches</command>
+ to <command>systemd-resolved</command> is equivalent to the <command>resolvectl --flush-caches</command>
command, however the latter is recommended since it operates in a synchronous way.</para></listitem>
</varlistentry>
@@ -243,7 +223,7 @@
should normally not be necessary to request this explicitly – except for debugging purposes – as
<command>systemd-resolved</command> automatically forgets learnt information any time the DNS server
configuration changes. Sending this signal to <command>systemd-resolved</command> is equivalent to the
- <command>systemd-resolve --reset-server-features</command> command, however the latter is recommended since it
+ <command>resolvectl --reset-server-features</command> command, however the latter is recommended since it
operates in a synchronous way.</para></listitem>
</varlistentry>
</variablelist>
@@ -257,7 +237,7 @@
<citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-resolve</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>resolvectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>hosts</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
diff --git a/man/systemd-rfkill.service.xml b/man/systemd-rfkill.service.xml
index cb6fae4c2d..d8c2ee25ff 100644
--- a/man/systemd-rfkill.service.xml
+++ b/man/systemd-rfkill.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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-rfkill.service" conditional='ENABLE_RFKILL'>
<refentryinfo>
<title>systemd-rfkill.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>
diff --git a/man/systemd-run.xml b/man/systemd-run.xml
index cfdbd2289f..1c254afae3 100644
--- a/man/systemd-run.xml
+++ b/man/systemd-run.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-run"
@@ -29,15 +12,6 @@
<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>
diff --git a/man/systemd-sleep.conf.xml b/man/systemd-sleep.conf.xml
index 7fecd667de..bd1f36aa62 100644
--- a/man/systemd-sleep.conf.xml
+++ b/man/systemd-sleep.conf.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-sleep.conf"
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-sleep.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -60,7 +34,7 @@
<refsect1>
<title>Description</title>
- <para><command>systemd</command> supports three general
+ <para><command>systemd</command> supports four general
power-saving modes:</para>
<variablelist>
@@ -102,6 +76,17 @@
suspend-to-both by the kernel.
</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>suspend-then-hibernate</term>
+
+ <listitem><para>A low power state where the system is initially suspended
+ (the state is stored in RAM). If not interrupted within the delay specified by
+ <command>HibernateDelaySec=</command>, the system will be woken using an RTC
+ alarm and hibernated (the state is then stored on disk).
+ </para></listitem>
+ </varlistentry>
+
</variablelist>
<para>Settings in these files determine what strings
@@ -111,7 +96,10 @@
<citerefentry><refentrytitle>systemd-sleep</refentrytitle><manvolnum>8</manvolnum></citerefentry>
when
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- attempts to suspend or hibernate the machine.</para>
+ attempts to suspend or hibernate the machine.
+ See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
@@ -134,8 +122,9 @@
<filename>/sys/power/disk</filename> by,
respectively,
<citerefentry><refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, or
- <citerefentry><refentrytitle>systemd-hybrid-sleep.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-hybrid-sleep.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, or
+ <citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
More than one value can be specified by separating
multiple values with whitespace. They will be tried
in turn, until one is written without error. If
@@ -152,14 +141,24 @@
<filename>/sys/power/state</filename> by,
respectively,
<citerefentry><refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, or
- <citerefentry><refentrytitle>systemd-hybrid-sleep.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-hybrid-sleep.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, or
+ <citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
More than one value can be specified by separating
multiple values with whitespace. They will be tried
in turn, until one is written without error. If
neither succeeds, the operation will be aborted.
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>HibernateDelaySec=</varname></term>
+
+ <listitem><para>The amount of time in seconds
+ that will pass before the system is automatically
+ put into hibernate when using
+ <citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -180,6 +179,7 @@ SuspendState=freeze</programlisting></para>
<citerefentry><refentrytitle>systemd-suspend.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-hybrid-sleep.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
diff --git a/man/systemd-socket-activate.xml b/man/systemd-socket-activate.xml
index 7cdd9d4c34..cb0065dfd3 100644
--- a/man/systemd-socket-activate.xml
+++ b/man/systemd-socket-activate.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-socket-activate"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-socket-activate</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-socket-proxyd.xml b/man/systemd-socket-proxyd.xml
index 1705374826..34a87ac8e4 100644
--- a/man/systemd-socket-proxyd.xml
+++ b/man/systemd-socket-proxyd.xml
@@ -5,22 +5,7 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2013 David Strauss
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 David Strauss
-->
<refentry id="systemd-socket-proxyd"
xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -28,14 +13,6 @@
<refentryinfo>
<title>systemd-socket-proxyd</title>
<productname>systemd</productname>
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Strauss</surname>
- <email>david@davidstrauss.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-socket-proxyd</refentrytitle>
@@ -124,7 +101,7 @@ Requires=proxy-to-nginx.socket
After=proxy-to-nginx.socket
[Service]
-ExecStart=/usr/lib/systemd/systemd-socket-proxyd /tmp/nginx.sock
+ExecStart=/usr/lib/systemd/systemd-socket-proxyd /run/nginx/socket
PrivateTmp=yes
PrivateNetwork=yes]]></programlisting>
</example>
@@ -133,7 +110,7 @@ PrivateNetwork=yes]]></programlisting>
<programlisting>
<![CDATA[[…]
server {
- listen unix:/tmp/nginx.sock;
+ listen unix:/run/nginx/socket;
[…]]]>
</programlisting>
</example>
diff --git a/man/systemd-suspend.service.xml b/man/systemd-suspend.service.xml
index 24c213eb74..cef7adb671 100644
--- a/man/systemd-suspend.service.xml
+++ b/man/systemd-suspend.service.xml
@@ -4,24 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-suspend.service"
@@ -30,15 +12,6 @@
<refentryinfo>
<title>systemd-suspend.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>
@@ -50,6 +23,7 @@
<refname>systemd-suspend.service</refname>
<refname>systemd-hibernate.service</refname>
<refname>systemd-hybrid-sleep.service</refname>
+ <refname>systemd-suspend-then-hibernate.service</refname>
<refname>systemd-sleep</refname>
<refpurpose>System sleep state logic</refpurpose>
</refnamediv>
@@ -58,6 +32,7 @@
<para><filename>systemd-suspend.service</filename></para>
<para><filename>systemd-hibernate.service</filename></para>
<para><filename>systemd-hybrid-sleep.service</filename></para>
+ <para><filename>systemd-suspend-then-hibernate.service</filename></para>
<para><filename>/usr/lib/systemd/system-sleep</filename></para>
</refsynopsisdiv>
@@ -72,7 +47,9 @@
hibernation. Finally,
<filename>systemd-hybrid-sleep.service</filename> is pulled in by
<filename>hybrid-sleep.target</filename> to execute hybrid
- hibernation with system suspend.</para>
+ hibernation with system suspend and pulled in by
+ <filename>suspend-then-hibernate.target</filename> to execute system suspend
+ with a timeout that will activate hibernate later.</para>
<para>Immediately before entering system suspend and/or
hibernation <filename>systemd-suspend.service</filename> (and the
@@ -80,8 +57,9 @@
<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 chosen action.
+ <literal>suspend</literal>, <literal>hibernate</literal>,
+ <literal>hybrid-sleep</literal>, or <literal>suspend-then-hibernate</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 directory are
@@ -100,6 +78,7 @@
<filename>systemd-suspend.service</filename>,
<filename>systemd-hibernate.service</filename>, and
<filename>systemd-hybrid-sleep.service</filename>
+ <filename>systemd-suspend-then-hibernate.service</filename>
should never be executed directly. Instead, trigger system sleep
states with a command such as <literal>systemctl suspend</literal>
or similar.</para>
@@ -128,9 +107,10 @@
<term><option>suspend</option></term>
<term><option>hibernate</option></term>
<term><option>hybrid-sleep</option></term>
+ <term><option>suspend-then-hibernate</option></term>
- <listitem><para>Suspend, hibernate, or put the system to
- hybrid sleep.</para>
+ <listitem><para>Suspend, hibernate, suspend then hibernate, or put the
+ system to hybrid sleep.</para>
</listitem>
</varlistentry>
</variablelist>
diff --git a/man/systemd-sysctl.service.xml b/man/systemd-sysctl.service.xml
index 3251bc6321..271240223a 100644
--- a/man/systemd-sysctl.service.xml
+++ b/man/systemd-sysctl.service.xml
@@ -3,23 +3,6 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-sysctl.service"
xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -27,15 +10,6 @@
<refentryinfo>
<title>systemd-sysctl.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>
@@ -92,6 +66,8 @@
</listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="cat-config" />
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
diff --git a/man/systemd-system-update-generator.xml b/man/systemd-system-update-generator.xml
index c57dc781db..a7b62b5288 100644
--- a/man/systemd-system-update-generator.xml
+++ b/man/systemd-system-update-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-system-update-generator">
<refentryinfo>
<title>systemd-system-update-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>
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index fca9690092..a914ef2523 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-system.conf"
@@ -31,15 +14,6 @@
<refentryinfo>
<title>systemd-system.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -76,7 +50,9 @@
<filename>user.conf</filename> and the files in
<filename>user.conf.d</filename> directories. These configuration
files contain a few settings controlling basic manager
- operations.</para>
+ operations. See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
@@ -157,31 +133,27 @@
<term><varname>RuntimeWatchdogSec=</varname></term>
<term><varname>ShutdownWatchdogSec=</varname></term>
- <listitem><para>Configure the hardware watchdog at runtime and
- at reboot. Takes a timeout value in seconds (or in other time
- units if suffixed with <literal>ms</literal>,
- <literal>min</literal>, <literal>h</literal>,
- <literal>d</literal>, <literal>w</literal>). If
- <varname>RuntimeWatchdogSec=</varname> is set to a non-zero
- value, the watchdog hardware
- (<filename>/dev/watchdog</filename> or the path specified with
- <varname>WatchdogDevice=</varname> or the kernel option
- <varname>systemd.watchdog-device=</varname>) will be programmed
- to automatically reboot the system if it is not contacted within
- the specified timeout interval. The system manager will ensure
- to contact it at least once in half the specified timeout
- interval. This feature requires a hardware watchdog device to
- be present, as it is commonly the case in embedded and server
- systems. Not all hardware watchdogs allow configuration of the
- reboot timeout, in which case the closest available timeout is
- picked. <varname>ShutdownWatchdogSec=</varname> may be used to
- configure the hardware watchdog when the system is asked to
- reboot. It works as a safety net to ensure that the reboot
- takes place even if a clean reboot attempt times out. By
- default <varname>RuntimeWatchdogSec=</varname> defaults to 0
- (off), and <varname>ShutdownWatchdogSec=</varname> to 10min.
- These settings have no effect if a hardware watchdog is not
- available.</para></listitem>
+ <listitem><para>Configure the hardware watchdog at runtime and at reboot. Takes a timeout value in seconds (or
+ in other time units if suffixed with <literal>ms</literal>, <literal>min</literal>, <literal>h</literal>,
+ <literal>d</literal>, <literal>w</literal>). If <varname>RuntimeWatchdogSec=</varname> is set to a non-zero
+ value, the watchdog hardware (<filename>/dev/watchdog</filename> or the path specified with
+ <varname>WatchdogDevice=</varname> or the kernel option <varname>systemd.watchdog-device=</varname>) will be
+ programmed to automatically reboot the system if it is not contacted within the specified timeout interval. The
+ system manager will ensure to contact it at least once in half the specified timeout interval. This feature
+ requires a hardware watchdog device to be present, as it is commonly the case in embedded and server
+ systems. Not all hardware watchdogs allow configuration of all possible reboot timeout values, in which case
+ the closest available timeout is picked. <varname>ShutdownWatchdogSec=</varname> may be used to configure the
+ hardware watchdog when the system is asked to reboot. It works as a safety net to ensure that the reboot takes
+ place even if a clean reboot attempt times out. Note that the <varname>ShutdownWatchdogSec=</varname> timeout
+ applies only to the second phase of the reboot, i.e. after all regular services are already terminated, and
+ after the system and service manager process (PID 1) got replaced by the <filename>systemd-shutdown</filename>
+ binary, see system <citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details. During the first phase of the shutdown operation the system and service manager remains running
+ and hence <varname>RuntimeWatchdogSec=</varname> is still honoured. In order to define a timeout on this first
+ phase of system shutdown, configure <varname>JobTimeoutSec=</varname> and <varname>JobTimeoutAction=</varname>
+ in the <literal>[Unit]</literal> section of the <filename>shutdown.target</filename> unit. By default
+ <varname>RuntimeWatchdogSec=</varname> defaults to 0 (off), and <varname>ShutdownWatchdogSec=</varname> to
+ 10min. These settings have no effect if a hardware watchdog is not available.</para></listitem>
</varlistentry>
<varlistentry>
@@ -216,6 +188,21 @@
</varlistentry>
<varlistentry>
+ <term><varname>NoNewPrivileges=</varname></term>
+
+ <listitem><para>Takes a boolean argument. If true, ensures that PID 1
+ and all its children can never gain new privileges through
+ <citerefentry project='man-pages'><refentrytitle>execve</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ (e.g. via setuid or setgid bits, or filesystem capabilities).
+ Defaults to false. General purpose distributions commonly rely
+ on executables with setuid or setgid bits and will thus not
+ function properly with this option enabled. Individual units
+ cannot disable this option.
+ Also see <ulink url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges Flag</ulink>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>SystemCallArchitectures=</varname></term>
<listitem><para>Takes a space-separated list of architecture
diff --git a/man/systemd-sysusers.xml b/man/systemd-sysusers.xml
index a55d9f6a75..7da2c55d27 100644
--- a/man/systemd-sysusers.xml
+++ b/man/systemd-sysusers.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-sysusers"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-sysusers</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -137,6 +111,8 @@
line instead of a file name.</para></listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="cat-config" />
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
diff --git a/man/systemd-sysv-generator.xml b/man/systemd-sysv-generator.xml
index 3eceb51381..0b07cc3cb3 100644
--- a/man/systemd-sysv-generator.xml
+++ b/man/systemd-sysv-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-sysv-generator" conditional="HAVE_SYSV_COMPAT">
<refentryinfo>
<title>systemd-sysv-generator</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Documentation</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-time-wait-sync.service.xml b/man/systemd-time-wait-sync.service.xml
new file mode 100644
index 0000000000..a967371246
--- /dev/null
+++ b/man/systemd-time-wait-sync.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">
+
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+
+ Copyright © 2018 Peter A. Bigot
+-->
+
+<refentry id="systemd-time-wait-sync.service" conditional='ENABLE_TIMESYNCD'>
+
+ <refentryinfo>
+ <title>systemd-time-wait-sync.service</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-time-wait-sync.service</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-time-wait-sync.service</refname>
+ <refname>systemd-time-wait-sync</refname>
+ <refpurpose>Wait Until Kernel Time Synchronized</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>systemd-time-wait-sync.service</filename></para>
+ <para><filename>/usr/lib/systemd/systemd-time-wait-sync</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><filename>systemd-time-wait-sync</filename> is a system service that delays the start of units that depend on
+ <filename>time-sync.target</filename> until the system time has been synchronized with an accurate time source by
+ <filename>systemd-timesyncd.service</filename>.</para>
+
+ <para><filename>systemd-timesyncd.service</filename> notifies on successful synchronization.
+ <filename>systemd-time-wait-sync</filename> also tries to detect when the kernel marks the time as synchronized,
+ but this detection is not reliable and is intended only as a fallback for other servies that can be used to
+ synchronize time (e.g., ntpd, chronyd).</para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Files</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><filename>/run/systemd/timesync/synchronized</filename></term>
+
+ <listitem>
+ <para>The presence of this file indicates to this service that the system clock has been synchronized.</para>
+ </listitem>
+
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd-timedated.service.xml b/man/systemd-timedated.service.xml
index 2dfde3c1b8..e334e8a848 100644
--- a/man/systemd-timedated.service.xml
+++ b/man/systemd-timedated.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-timedated.service" conditional='ENABLE_TIMEDATED'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-timedated.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>
@@ -75,12 +49,33 @@
</refsect1>
<refsect1>
+ <title>Environment</title>
+
+ <variablelist class='environment-variables'>
+ <varlistentry>
+ <term><varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname></term>
+
+ <listitem><para>Colon-separated list of unit names of NTP client services.
+ If not set, then
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ is used. See the entries of NTP related commands of
+ <citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ for details about this.</para>
+
+ <para>Example:
+ <programlisting>SYSTEMD_TIMEDATED_NTP_SERVICES=ntpd.service:chronyd.service:systemd-timesyncd.service</programlisting>
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>localtime</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>hwclock</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry project='man-pages'><refentrytitle>hwclock</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-timesyncd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-timesyncd.service.xml b/man/systemd-timesyncd.service.xml
index e9b5c25780..cdea1067a0 100644
--- a/man/systemd-timesyncd.service.xml
+++ b/man/systemd-timesyncd.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 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/>.
-->
<refentry id="systemd-timesyncd.service" conditional='ENABLE_TIMESYNCD'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd-timesyncd.service</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -83,6 +57,10 @@
<para><citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
<command>set-ntp</command> command may be used to enable and
start, or disable and stop this service.</para>
+
+ <para><citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
+ <command>timesync-status</command> or <command>show-timesync</command> command can be used to show the
+ current status of this service.</para>
</refsect1>
<refsect1>
@@ -93,10 +71,22 @@
<term><filename>/var/lib/systemd/timesync/clock</filename></term>
<listitem>
- <para>This file contains the timestamp of the last successful
- synchronization.</para>
+ <para>The modification time of this file indicates the timestamp of the last successful
+ synchronization (or at least the systemd build date, in case synchronization was not
+ possible).</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><filename>/run/systemd/timesync/synchronized</filename></term>
+
+ <listitem>
+ <para>A file that is touched on each successful synchronization, to assist
+ <filename>systemd-time-wait-sync</filename> and other applications to detecting synchronization
+ events.</para>
+ </listitem>
+
+ </varlistentry>
</variablelist>
</refsect1>
@@ -107,6 +97,7 @@
<citerefentry><refentrytitle>timesyncd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-time-wait-sync.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>localtime</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>hwclock</refentrytitle><manvolnum>8</manvolnum></citerefentry>
diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml
index 7c64dfaf58..9ff114feef 100644
--- a/man/systemd-tmpfiles.xml
+++ b/man/systemd-tmpfiles.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-tmpfiles"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-tmpfiles</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -196,6 +170,8 @@
</para></listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="cat-config" />
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
@@ -231,7 +207,7 @@
<filename>/usr/include/sysexits.h</filename>). If the configuration was syntactically valid, but
could not be executed (lack of permissions, creation of files in missing directories, invalid
contents when writing to <filename>/sys/</filename> values, …), <constant>73</constant> is
- returned (<constant>EX_DATAERR</constant> from <filename>/usr/include/sysexits.h</filename>).
+ returned (<constant>EX_CANTCREAT</constant> from <filename>/usr/include/sysexits.h</filename>).
Otherwise, <constant>1</constant> is returned (<constant>EXIT_FAILURE</constant> from
<filename>/usr/include/stdlib.h</filename>).
</para>
diff --git a/man/systemd-tty-ask-password-agent.xml b/man/systemd-tty-ask-password-agent.xml
index e934649ed9..75ab0322db 100644
--- a/man/systemd-tty-ask-password-agent.xml
+++ b/man/systemd-tty-ask-password-agent.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-tty-ask-password-agent"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd-tty-ask-password-agent</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml
index ee18dae6eb..73c77ea690 100644
--- a/man/systemd-udevd.service.xml
+++ b/man/systemd-udevd.service.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010-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/>.
-->
<refentry id="systemd-udevd.service"
@@ -29,14 +12,6 @@
<refentryinfo>
<title>systemd-udevd.service</title>
<productname>systemd</productname>
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd-update-done.service.xml b/man/systemd-update-done.service.xml
index b0dd56fdff..fa88e66f96 100644
--- a/man/systemd-update-done.service.xml
+++ b/man/systemd-update-done.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-update-done.service">
<refentryinfo>
<title>systemd-update-done.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>
diff --git a/man/systemd-update-utmp.service.xml b/man/systemd-update-utmp.service.xml
index 286c18ed4c..a3822ac987 100644
--- a/man/systemd-update-utmp.service.xml
+++ b/man/systemd-update-utmp.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-update-utmp.service" conditional="ENABLE_UTMP">
<refentryinfo>
<title>systemd-update-utmp.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>
diff --git a/man/systemd-user-sessions.service.xml b/man/systemd-user-sessions.service.xml
index c3eaffa242..52fc0d7167 100644
--- a/man/systemd-user-sessions.service.xml
+++ b/man/systemd-user-sessions.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-user-sessions.service" conditional='HAVE_PAM'>
<refentryinfo>
<title>systemd-user-sessions.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>
diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml
index 3b72234b0f..08c5d8116f 100644
--- a/man/systemd-vconsole-setup.service.xml
+++ b/man/systemd-vconsole-setup.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd-vconsole-setup.service" conditional='ENABLE_VCONSOLE'>
<refentryinfo>
<title>systemd-vconsole-setup.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>
diff --git a/man/systemd-veritysetup-generator.xml b/man/systemd-veritysetup-generator.xml
index b6b5b3bc51..f9f645fe9b 100644
--- a/man/systemd-veritysetup-generator.xml
+++ b/man/systemd-veritysetup-generator.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-veritysetup-generator" conditional='HAVE_LIBCRYPTSETUP'>
<refentryinfo>
<title>systemd-veritysetup-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>
diff --git a/man/systemd-veritysetup@.service.xml b/man/systemd-veritysetup@.service.xml
index 55600e9ad5..7701409d3b 100644
--- a/man/systemd-veritysetup@.service.xml
+++ b/man/systemd-veritysetup@.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-veritysetup@.service" conditional='HAVE_LIBCRYPTSETUP'>
<refentryinfo>
<title>systemd-veritysetup@.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>
diff --git a/man/systemd-volatile-root.service.xml b/man/systemd-volatile-root.service.xml
index ee7c8b3762..651832f36b 100644
--- a/man/systemd-volatile-root.service.xml
+++ b/man/systemd-volatile-root.service.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd-volatile-root.service">
<refentryinfo>
<title>systemd-volatile-root.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>
diff --git a/man/systemd.automount.xml b/man/systemd.automount.xml
index b0f5b19372..2e55ad0b68 100644
--- a/man/systemd.automount.xml
+++ b/man/systemd.automount.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.automount">
<refentryinfo>
<title>systemd.automount</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -89,30 +63,34 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
+ <title>Automatic Dependencies</title>
- <para>The following dependencies are implicitly added:</para>
+ <refsect2>
+ <title>Implicit Dependencies</title>
- <itemizedlist>
- <listitem><para>If an automount unit is beneath another mount unit in the
- file system hierarchy, both a requirement and an ordering
- dependency between both units are created automatically.</para></listitem>
+ <para>The following dependencies are implicitly added:</para>
- <listitem><para>An implicit <varname>Before=</varname> dependency is created
- between an automount unit and the mount unit it activates.</para></listitem>
- </itemizedlist>
- </refsect1>
+ <itemizedlist>
+ <listitem><para>If an automount unit is beneath another mount unit in the
+ file system hierarchy, both a requirement and an ordering
+ dependency between both units are created automatically.</para></listitem>
- <refsect1>
- <title>Default Dependencies</title>
+ <listitem><para>An implicit <varname>Before=</varname> dependency is created
+ between an automount unit and the mount unit it activates.</para></listitem>
+ </itemizedlist>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
- <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
+ <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
- <itemizedlist>
- <listitem><para>Automount units acquire automatic <varname>Before=</varname> and
- <varname>Conflicts=</varname> on <filename>umount.target</filename> in order to be stopped during
- shutdown.</para></listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem><para>Automount units acquire automatic <varname>Before=</varname> and
+ <varname>Conflicts=</varname> on <filename>umount.target</filename> in order to be stopped during
+ shutdown.</para></listitem>
+ </itemizedlist>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd.device.xml b/man/systemd.device.xml
index a275a880e4..0144704109 100644
--- a/man/systemd.device.xml
+++ b/man/systemd.device.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.device">
<refentryinfo>
<title>systemd.device</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -90,25 +64,28 @@
corresponding device generates a <literal>changed</literal> event.
Other units can use <varname>ReloadPropagatedFrom=</varname> to react
to that event</para>
-
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
-
- <para>Many unit types automatically acquire dependencies on device
- units of devices they require. For example,
- <filename>.socket</filename> unit acquire dependencies on the
- device units of the network interface specified in
- <varname>BindToDevice=</varname>. Similar, swap and mount units
- acquire dependencies on the units encapsulating their backing
- block devices.</para>
- </refsect1>
+ <title>Automatic Dependencies</title>
- <refsect1>
- <title>Default Dependencies</title>
+ <refsect2>
+ <title>Implicit Dependencies</title>
+
+ <para>Many unit types automatically acquire dependencies on device
+ units of devices they require. For example,
+ <filename>.socket</filename> unit acquire dependencies on the
+ device units of the network interface specified in
+ <varname>BindToDevice=</varname>. Similar, swap and mount units
+ acquire dependencies on the units encapsulating their backing
+ block devices.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
- <para>There are no default dependencies for device units.</para>
+ <para>There are no default dependencies for device units.</para>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd.dnssd.xml b/man/systemd.dnssd.xml
index 054f6615c2..b3a4c68e3f 100644
--- a/man/systemd.dnssd.xml
+++ b/man/systemd.dnssd.xml
@@ -3,22 +3,6 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of systemd.
-
- Copyright 2017 Dmitry Rozhkov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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.dnssd" conditional='ENABLE_RESOLVE'>
@@ -26,15 +10,6 @@
<refentryinfo>
<title>systemd.dnssd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Dmitry</firstname>
- <surname>Rozhkov</surname>
- <email>dmitry.rozhkov@intel.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -214,10 +189,10 @@ TxtText=path=/stats/index.html t=temperature_sensor</programlisting>
<para>This makes the http server running on the host discoverable in the local network
given MulticastDNS is enabled on the network interface.</para>
- <para>Now the utility <literal>systemd-resolve</literal> should be able to resolve the
+ <para>Now the utility <literal>resolvectl</literal> should be able to resolve the
service to the host's name:</para>
- <programlisting>$ systemd-resolve --service meteo._http._tcp.local
+ <programlisting>$ resolvectl service meteo._http._tcp.local
meteo._http._tcp.local: meteo.local:80 [priority=0, weight=0]
169.254.208.106%senp0s21f0u2u4
fe80::213:3bff:fe49:8aa%senp0s21f0u2u4
@@ -251,7 +226,8 @@ meteo._http._tcp.local: meteo.local:80 [priority=0, weight=0]
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>resolvectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd.environment-generator.xml b/man/systemd.environment-generator.xml
index d5e773e5e3..4595a99572 100644
--- a/man/systemd.environment-generator.xml
+++ b/man/systemd.environment-generator.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.environment-generator" conditional='ENABLE_ENVIRONMENT_D'
@@ -31,15 +14,6 @@
<refentryinfo>
<title>systemd.environment-generator</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index f1bbfb94a2..a532b74a6e 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.exec">
<refentryinfo>
<title>systemd.exec</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -326,7 +300,7 @@
inverted. Note that this option also affects the respective capabilities in the effective, permitted and
inheritable capability sets. If this option is not used, the capability bounding set is not modified on process
execution, hence no limits on the capabilities of the process are enforced. This option may appear more than
- once, in which case the bounding sets are merged by <constant>AND</constant>, or by <constant>OR</constant> if
+ once, in which case the bounding sets are merged by <constant>OR</constant>, or by <constant>AND</constant> if
the lines are prefixed with <literal>~</literal> (see below). If the empty string is assigned to this 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 reset to the full set of available
@@ -366,7 +340,6 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
</variablelist>
</refsect1>
-
<refsect1>
<title>Security</title>
@@ -742,7 +715,8 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<listitem><para>Sets the I/O scheduling class for executed processes. Takes an integer between 0 and 3 or one
of the strings <option>none</option>, <option>realtime</option>, <option>best-effort</option> or
- <option>idle</option>. See
+ <option>idle</option>. If the empty string is assigned to this option, all prior assignments to both
+ <varname>IOSchedulingClass=</varname> and <varname>IOSchedulingPriority=</varname> have no effect. See
<citerefentry><refentrytitle>ioprio_set</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
details.</para></listitem>
</varlistentry>
@@ -752,14 +726,15 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<listitem><para>Sets the I/O scheduling priority for executed processes. Takes an integer between 0 (highest
priority) and 7 (lowest priority). The available priorities depend on the selected I/O scheduling class (see
- above). See <citerefentry><refentrytitle>ioprio_set</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
+ above). If the empty string is assigned to this option, all prior assignments to both
+ <varname>IOSchedulingClass=</varname> and <varname>IOSchedulingPriority=</varname> have no effect.
+ See <citerefentry><refentrytitle>ioprio_set</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
details.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
-
<refsect1>
<title>Sandboxing</title>
@@ -797,7 +772,7 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
are still visible by combining with <varname>BindPaths=</varname> or <varname>BindReadOnlyPaths=</varname>.</para>
<para>Setting this to <literal>yes</literal> is mostly equivalent to set the three directories in
- <varname>InaccessiblePaths=</varname>. Similary, <literal>read-only</literal> is mostly equivalent to
+ <varname>InaccessiblePaths=</varname>. Similarly, <literal>read-only</literal> is mostly equivalent to
<varname>ReadOnlyPaths=</varname>, and <literal>tmpfs</literal> is mostly equivalent to
<varname>TemporaryFileSystem=</varname>.</para>
@@ -816,13 +791,48 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<term><varname>ConfigurationDirectory=</varname></term>
<listitem><para>These options take a whitespace-separated list of directory names. The specified directory
- names must be relative, and may not include <literal>.</literal> or <literal>..</literal>. If set, one or more
- directories by the specified names will be created (including their parents) below <filename>/run</filename>
- (or <varname>$XDG_RUNTIME_DIR</varname> for user services), <filename>/var/lib</filename> (or
- <varname>$XDG_CONFIG_HOME</varname> for user services), <filename>/var/cache</filename> (or
- <varname>$XDG_CACHE_HOME</varname> for user services), <filename>/var/log</filename> (or
- <varname>$XDG_CONFIG_HOME</varname><filename>/log</filename> for user services), or <filename>/etc</filename>
- (or <varname>$XDG_CONFIG_HOME</varname> for user services), respectively, when the unit is started.</para>
+ names must be relative, and may not include <literal>..</literal>. If set, one or more
+ directories by the specified names will be created (including their parents) below the locations
+ defined in the following table, when the unit is started.</para>
+ <table>
+ <title>Automatic directory creation</title>
+ <tgroup cols='3'>
+ <thead>
+ <row>
+ <entry>Locations</entry>
+ <entry>for system</entry>
+ <entry>for users</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><varname>RuntimeDirectory=</varname></entry>
+ <entry><filename>/run</filename></entry>
+ <entry><varname>$XDG_RUNTIME_DIR</varname></entry>
+ </row>
+ <row>
+ <entry><varname>StateDirectory=</varname></entry>
+ <entry><filename>/var/lib</filename></entry>
+ <entry><varname>$XDG_CONFIG_HOME</varname></entry>
+ </row>
+ <row>
+ <entry><varname>CacheDirectory=</varname></entry>
+ <entry><filename>/var/cache</filename></entry>
+ <entry><varname>$XDG_CACHE_HOME</varname></entry>
+ </row>
+ <row>
+ <entry><varname>LogsDirectory=</varname></entry>
+ <entry><filename>/var/log</filename></entry>
+ <entry><varname>$XDG_CONFIG_HOME</varname><filename>/log</filename></entry>
+ </row>
+ <row>
+ <entry><varname>ConfigurationDirectory=</varname></entry>
+ <entry><filename>/etc</filename></entry>
+ <entry><varname>$XDG_CONFIG_HOME</varname></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
<para>In case of <varname>RuntimeDirectory=</varname> the lowest subdirectories are removed when the unit is
stopped. It is possible to preserve the specified directories in this case if
@@ -1092,8 +1102,8 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
<varlistentry>
<term><varname>ProtectKernelModules=</varname></term>
- <listitem><para>Takes a boolean argument. If true, explicit module loading will be denied. This allows to turn
- off module load and unload operations on modular kernels. It is recommended to turn this on for most services
+ <listitem><para>Takes a boolean argument. If true, explicit module loading will be denied. This allows
+ module load and unload operations to be turned off on modular kernels. It is recommended to turn this on for most services
that do not need special file systems or extra kernel modules to work. Defaults to off. Enabling this option
removes <constant>CAP_SYS_MODULE</constant> from the capability bounding set for the unit, and installs a
system call filter to block module system calls, also <filename>/usr/lib/modules</filename> is made
@@ -1167,7 +1177,9 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
prohibited (whitelisting). By prepending the list with a single tilde character (<literal>~</literal>) the
effect may be inverted: only the listed namespace types will be made inaccessible, all unlisted ones are
permitted (blacklisting). If the empty string is assigned, the default namespace restrictions are applied,
- which is equivalent to false. Internally, this setting limits access to the
+ which is equivalent to false. This option may appear more than once, in which case the namespace types are
+ merged by <constant>OR</constant>, or by <constant>AND</constant> if the lines are prefixed with
+ <literal>~</literal> (see examples below). Internally, this setting limits access to the
<citerefentry><refentrytitle>unshare</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
<citerefentry><refentrytitle>clone</refentrytitle><manvolnum>2</manvolnum></citerefentry> and
<citerefentry><refentrytitle>setns</refentrytitle><manvolnum>2</manvolnum></citerefentry> system calls, taking
@@ -1177,7 +1189,16 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
supported on x86, x86-64, mips, mips-le, mips64, mips64-le, mips64-n32, mips64-le-n32, ppc64, ppc64-le, s390
and s390x, and enforces no restrictions on other architectures. If running in user mode, or in system mode, but
without the <constant>CAP_SYS_ADMIN</constant> capability (e.g. setting <varname>User=</varname>),
- <varname>NoNewPrivileges=yes</varname> is implied. </para></listitem>
+ <varname>NoNewPrivileges=yes</varname> is implied.</para>
+
+ <para>Example: if a unit has the following,
+ <programlisting>RestrictNamespaces=cgroup ipc
+RestrictNamespaces=cgroup net</programlisting>
+ then <constant>cgroup</constant>, <constant>ipc</constant>, and <constant>net</constant> are set.
+ If the second line is prefixed with <literal>~</literal>, e.g.,
+ <programlisting>RestrictNamespaces=cgroup ipc
+RestrictNamespaces=~cgroup net</programlisting>
+ then, only <constant>ipc</constant> is set.</para></listitem>
</varlistentry>
<varlistentry>
@@ -1244,27 +1265,68 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
</varlistentry>
<varlistentry>
+ <term><varname>PrivateMounts=</varname></term>
+
+ <listitem><para>Takes a boolean parameter. If set, the processes of this unit will be run in their own private
+ file system (mount) namespace with all mount propagation from the processes towards the host's main file system
+ namespace turned off. This means any file system mount points established or removed by the unit's processes
+ will be private to them and not be visible to the host. However, file system mount points established or
+ removed on the host will be propagated to the unit's processes. See <citerefentry
+ project='man-pages'><refentrytitle>mount_namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
+ details on file system namespaces. Defaults to off.</para>
+
+ <para>When turned on, this executes three operations for each invoked process: a new
+ <constant>CLONE_NEWNS</constant> namespace is created, after which all existing mounts are remounted to
+ <constant>MS_SLAVE</constant> to disable propagation from the unit's processes to the host (but leaving
+ propagation in the opposite direction in effect). Finally, the mounts are remounted again to the propagation
+ mode configured with <varname>MountFlags=</varname>, see below.</para>
+
+ <para>File system namespaces are set up individually for each process forked off by the service manager. Mounts
+ established in the namespace of the process created by <varname>ExecStartPre=</varname> will hence be cleaned
+ up automatically as soon as that process exits and will not be available to subsequent processes forked off for
+ <varname>ExecStart=</varname> (and similar applies to the various other commands configured for
+ units). Similarly, <varname>JoinsNamespaceOf=</varname> does not permit sharing kernel mount namespaces between
+ units, it only enables sharing of the <filename>/tmp/</filename> and <filename>/var/tmp/</filename>
+ directories.</para>
+
+ <para>Other file system namespace unit settings — <varname>PrivateMounts=</varname>,
+ <varname>PrivateTmp=</varname>, <varname>PrivateDevices=</varname>, <varname>ProtectSystem=</varname>,
+ <varname>ProtectHome=</varname>, <varname>ReadOnlyPaths=</varname>, <varname>InaccessiblePaths=</varname>,
+ <varname>ReadWritePaths=</varname>, … — also enable file system namespacing in a fashion equivalent to this
+ option. Hence it is primarily useful to explicitly request this behaviour if none of the other settings are
+ used.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>MountFlags=</varname></term>
- <listitem><para>Takes a mount propagation flag: <option>shared</option>, <option>slave</option> or
- <option>private</option>, which control whether mounts in the file system namespace set up for this unit's
- processes will receive or propagate mounts and unmounts. See <citerefentry
- project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
- details. Defaults to <option>shared</option>. Use <option>shared</option> to ensure that mounts and unmounts
- are propagated from systemd's namespace to the service's namespace and vice versa. Use <option>slave</option>
- to run processes so that none of their mounts and unmounts will propagate to the host. Use
- <option>private</option> to also ensure that no mounts and unmounts from the host will propagate into the unit
- processes' namespace. If this is set to <option>slave</option> or <option>private</option>, any mounts created
- by spawned processes will be unmounted after the completion of the current command line of
- <varname>ExecStartPre=</varname>, <varname>ExecStartPost=</varname>, <varname>ExecStart=</varname>, and
- <varname>ExecStopPost=</varname>. Note that <option>slave</option> means that file systems mounted on the host
- might stay mounted continuously in the unit's namespace, and thus keep the device busy. Note that the file
- system namespace related options (<varname>PrivateTmp=</varname>, <varname>PrivateDevices=</varname>,
- <varname>ProtectSystem=</varname>, <varname>ProtectHome=</varname>, <varname>ProtectKernelTunables=</varname>,
- <varname>ProtectControlGroups=</varname>, <varname>ReadOnlyPaths=</varname>,
- <varname>InaccessiblePaths=</varname>, <varname>ReadWritePaths=</varname>) require that mount and unmount
- propagation from the unit's file system namespace is disabled, and hence downgrade <option>shared</option> to
- <option>slave</option>. </para></listitem>
+ <listitem><para>Takes a mount propagation setting: <option>shared</option>, <option>slave</option> or
+ <option>private</option>, which controls whether file system mount points in the file system namespaces set up
+ for this unit's processes will receive or propagate mounts and unmounts from other file system namespaces. See
+ <citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ for details on mount propagation, and the three propagation flags in particular.</para>
+
+ <para>This setting only controls the <emphasis>final</emphasis> propagation setting in effect on all mount
+ points of the file system namespace created for each process of this unit. Other file system namespacing unit
+ settings (see the discussion in <varname>PrivateMounts=</varname> above) will implicitly disable mount and
+ unmount propagation from the unit's processes towards the host by changing the propagation setting of all mount
+ points in the unit's file system namepace to <option>slave</option> first. Setting this option to
+ <option>shared</option> does not reestablish propagation in that case. Conversely, if this option is set, but
+ no other file system namespace setting is used, then new file system namespaces will be created for the unit's
+ processes and this propagation flag will be applied right away to all mounts within it, without the
+ intermediary application of <option>slave</option>.</para>
+
+ <para>If not set – but file system namespaces are enabled through another file system namespace unit setting –
+ <option>shared</option> mount propagation is used, but — as mentioned — as <option>slave</option> is applied
+ first, propagation from the unit's processes to the host is still turned off.</para>
+
+ <para>It is not recommended to to use <option>private</option> mount propagation for units, as this means
+ temporary mounts (such as removable media) of the host will stay mounted and thus indefinitely busy in forked
+ off processes, as unmount propagation events won't be received by the file system namespace of the unit.</para>
+
+ <para>Usually, it is best to leave this setting unmodified, and use higher level file system namespacing
+ options instead, in particular <varname>PrivateMounts=</varname>, see above.</para>
+ </listitem>
</varlistentry>
</variablelist>
@@ -1429,6 +1491,10 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
<entry>Synchronizing files and memory to disk: (<citerefentry project='man-pages'><refentrytitle>fsync</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>msync</refentrytitle><manvolnum>2</manvolnum></citerefentry>, and related calls)</entry>
</row>
<row>
+ <entry>@system-service</entry>
+ <entry>A reasonable set of system calls used by common system services, excluding any special purpose calls. This is the recommended starting point for whitelisting system calls for system services, as it contains what is typically needed by system services, but excludes overly specific interfaces. For example, the following APIs are excluded: <literal>@clock</literal>, <literal>@mount</literal>, <literal>@swap</literal>, <literal>@reboot</literal>.</entry>
+ </row>
+ <row>
<entry>@timer</entry>
<entry>System calls for scheduling operations by time (<citerefentry project='man-pages'><refentrytitle>alarm</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>timer_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>, …)</entry>
</row>
@@ -1442,6 +1508,14 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
<command>systemd-analyze syscall-filter</command> to list the actual list of system calls in each
filter.</para>
+ <para>Generally, whitelisting system calls (rather than blacklisting) is the safer mode of operation. It is
+ recommended to enforce system call whitelists for all long-running system services. Specifically, the
+ following lines are a relatively safe basic choice for the majority of system services:</para>
+
+ <programlisting>[Service]
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM</programlisting>
+
<para>It is recommended to combine the file system namespacing related options with
<varname>SystemCallFilter=~@mount</varname>, in order to prohibit the unit's processes to undo the
mappings. Specifically these are the options <varname>PrivateTmp=</varname>,
@@ -1707,8 +1781,8 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
<para>The <option>file:<replaceable>path</replaceable></option> option may be used to connect a specific file
system object to standard output. The semantics are similar to the same option of
- <varname>StandardInputText=</varname>, see above. If standard input and output are directed to the same file
- path, it is opened only once, for reading as well as writing and duplicated. This is particular useful when the
+ <varname>StandardInput=</varname>, see above. If standard input and output are directed to the same file path,
+ it is opened only once, for reading as well as writing and duplicated. This is particular useful when the
specified path refers to an <constant>AF_UNIX</constant> socket in the file system, as in that case only a
single stream connection is created for both input and output.</para>
@@ -1765,7 +1839,7 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
<para><varname>StandardInputText=</varname> accepts arbitrary textual data. C-style escapes for special
characters as well as the usual <literal>%</literal>-specifiers are resolved. Each time this setting is used
- the the specified text is appended to the per-unit data buffer, followed by a newline character (thus every use
+ the specified text is appended to the per-unit data buffer, followed by a newline character (thus every use
appends a new line to the end of the buffer). Note that leading and trailing whitespace of lines configured
with this option is removed. If an empty line is specified the buffer is cleared (hence, in order to insert an
empty line, add an additional <literal>\n</literal> to the end or beginning of a line).</para>
@@ -1806,7 +1880,7 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
details. By default no filtering is applied (i.e. the default maximum log level is <option>debug</option>). Use
this option to configure the logging system to drop log messages of a specific service above the specified
level. For example, set <varname>LogLevelMax=</varname><option>info</option> in order to turn off debug logging
- of a particularly chatty unit. Note that the the configured level is applied to any log messages written by any
+ of a particularly chatty unit. Note that the configured level is applied to any log messages written by any
of the processes belonging to this unit, sent via any supported logging protocol. The filtering is applied
early in the logging pipeline, before any kind of further processing is done. Moreover, messages which pass
through this filter successfully might still be dropped by filters applied at a later stage in the logging
@@ -2622,6 +2696,98 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
</tbody>
</tgroup>
</table>
+
+ <para>Finally, the BSD operating systems define a set of exit codes, typically defined on Linux systems too:</para>
+
+ <table>
+ <title>BSD exit codes</title>
+ <tgroup cols='3'>
+ <thead>
+ <row>
+ <entry>Exit Code</entry>
+ <entry>Symbolic Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>64</entry>
+ <entry><constant>EX_USAGE</constant></entry>
+ <entry>Command line usage error</entry>
+ </row>
+ <row>
+ <entry>65</entry>
+ <entry><constant>EX_DATAERR</constant></entry>
+ <entry>Data format error</entry>
+ </row>
+ <row>
+ <entry>66</entry>
+ <entry><constant>EX_NOINPUT</constant></entry>
+ <entry>Cannot open input</entry>
+ </row>
+ <row>
+ <entry>67</entry>
+ <entry><constant>EX_NOUSER</constant></entry>
+ <entry>Addressee unknown</entry>
+ </row>
+ <row>
+ <entry>68</entry>
+ <entry><constant>EX_NOHOST</constant></entry>
+ <entry>Host name unknown</entry>
+ </row>
+ <row>
+ <entry>69</entry>
+ <entry><constant>EX_UNAVAILABLE</constant></entry>
+ <entry>Service unavailable</entry>
+ </row>
+ <row>
+ <entry>70</entry>
+ <entry><constant>EX_SOFTWARE</constant></entry>
+ <entry>internal software error</entry>
+ </row>
+ <row>
+ <entry>71</entry>
+ <entry><constant>EX_OSERR</constant></entry>
+ <entry>System error (e.g., can't fork)</entry>
+ </row>
+ <row>
+ <entry>72</entry>
+ <entry><constant>EX_OSFILE</constant></entry>
+ <entry>Critical OS file missing</entry>
+ </row>
+ <row>
+ <entry>73</entry>
+ <entry><constant>EX_CANTCREAT</constant></entry>
+ <entry>Can't create (user) output file</entry>
+ </row>
+ <row>
+ <entry>74</entry>
+ <entry><constant>EX_IOERR</constant></entry>
+ <entry>Input/output error</entry>
+ </row>
+ <row>
+ <entry>75</entry>
+ <entry><constant>EX_TEMPFAIL</constant></entry>
+ <entry>Temporary failure; user is invited to retry</entry>
+ </row>
+ <row>
+ <entry>76</entry>
+ <entry><constant>EX_PROTOCOL</constant></entry>
+ <entry>Remote error in protocol</entry>
+ </row>
+ <row>
+ <entry>77</entry>
+ <entry><constant>EX_NOPERM</constant></entry>
+ <entry>Permission denied</entry>
+ </row>
+ <row>
+ <entry>78</entry>
+ <entry><constant>EX_CONFIG</constant></entry>
+ <entry>Configuration error</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
</refsect1>
<refsect1>
@@ -2645,5 +2811,4 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
</para>
</refsect1>
-
</refentry>
diff --git a/man/systemd.generator.xml b/man/systemd.generator.xml
index 60ca0cecad..8a7a11a862 100644
--- a/man/systemd.generator.xml
+++ b/man/systemd.generator.xml
@@ -7,38 +7,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 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.generator">
<refentryinfo>
<title>systemd.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>
diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml
index 15a166280b..c079274c32 100644
--- a/man/systemd.journal-fields.xml
+++ b/man/systemd.journal-fields.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.journal-fields">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd.journal-fields</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd.kill.xml b/man/systemd.kill.xml
index 1abcd6d8e7..2112dea31a 100644
--- a/man/systemd.kill.xml
+++ b/man/systemd.kill.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd.kill">
<refentryinfo>
<title>systemd.kill</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd.link.xml b/man/systemd.link.xml
index 794e0e06fc..6708753e82 100644
--- a/man/systemd.link.xml
+++ b/man/systemd.link.xml
@@ -4,37 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.link">
<refentryinfo>
<title>systemd.link</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -101,7 +76,12 @@
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem>
- <para>The hardware address.</para>
+ <para>A whitespace-separated list of hardware addresses. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example below.
+ This option may appear more than once, in which case the lists are merged. If the empty string is assigned to this option, the list
+ of hardware addresses defined prior to this is reset.</para>
+
+ <para>Example:
+ <programlisting>MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
@@ -522,14 +502,6 @@
Defaults to "unset".</para>
</listitem>
</varlistentry>
- <varlistentry>
- <term><varname>UDPSegmentationOffload=</varname></term>
- <listitem>
- <para>The UDP Segmentation Offload (USO) when true enables
- UDP segmentation offload. Takes a boolean value.
- Defaults to "unset".</para>
- </listitem>
- </varlistentry>
<varlistentry>
<term><varname>GenericReceiveOffload=</varname></term>
<listitem>
@@ -546,6 +518,30 @@
Defaults to "unset".</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>RxChannels=</varname></term>
+ <listitem>
+ <para>Sets the number of receive channels (a number between 1 and 4294967295) .</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>TxChannels=</varname></term>
+ <listitem>
+ <para>Sets the number of transmit channels (a number between 1 and 4294967295).</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>OtherChannels=</varname></term>
+ <listitem>
+ <para>Sets the number of other channels (a number between 1 and 4294967295).</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>CombinedChannels=</varname></term>
+ <listitem>
+ <para>Sets the number of combined set channels (a number between 1 and 4294967295).</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml
index 8607bd797f..1eb06b0ea8 100644
--- a/man/systemd.mount.xml
+++ b/man/systemd.mount.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.mount">
<refentryinfo>
<title>systemd.mount</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -115,57 +89,61 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
-
- <para>The following dependencies are implicitly added:</para>
-
- <itemizedlist>
- <listitem><para>If a mount unit is beneath another mount unit in the file
- system hierarchy, both a requirement dependency and an ordering
- dependency between both units are created automatically.</para></listitem>
-
- <listitem><para>Block device backed file systems automatically gain
- <varname>BindsTo=</varname> and <varname>After=</varname> type
- dependencies on the device unit encapsulating the block
- device (see below).</para></listitem>
-
- <listitem><para>If traditional file system quota is enabled for a mount
- unit, automatic <varname>Wants=</varname> and
- <varname>Before=</varname> dependencies on
- <filename>systemd-quotacheck.service</filename> and
- <filename>quotaon.service</filename> are added.</para></listitem>
-
- <listitem><para>Additional implicit dependencies may be added as result of
- execution and resource control parameters as documented in
- <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- and
- <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- </para></listitem>
- </itemizedlist>
- </refsect1>
+ <title>Automatic Dependencies</title>
+
+ <refsect2>
+ <title>Implicit Dependencies</title>
+
+ <para>The following dependencies are implicitly added:</para>
+
+ <itemizedlist>
+ <listitem><para>If a mount unit is beneath another mount unit in the file
+ system hierarchy, both a requirement dependency and an ordering
+ dependency between both units are created automatically.</para></listitem>
+
+ <listitem><para>Block device backed file systems automatically gain
+ <varname>BindsTo=</varname> and <varname>After=</varname> type
+ dependencies on the device unit encapsulating the block
+ device (see below).</para></listitem>
+
+ <listitem><para>If traditional file system quota is enabled for a mount
+ unit, automatic <varname>Wants=</varname> and
+ <varname>Before=</varname> dependencies on
+ <filename>systemd-quotacheck.service</filename> and
+ <filename>quotaon.service</filename> are added.</para></listitem>
+
+ <listitem><para>Additional implicit dependencies may be added as result of
+ execution and resource control parameters as documented in
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </itemizedlist>
+ </refsect2>
- <refsect1>
- <title>Default Dependencies</title>
+ <refsect2>
+ <title>Default Dependencies</title>
- <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
+ <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
- <itemizedlist>
- <listitem><para>All mount units acquire automatic <varname>Before=</varname> and <varname>Conflicts=</varname> on
- <filename>umount.target</filename> in order to be stopped during shutdown.</para></listitem>
+ <itemizedlist>
+ <listitem><para>All mount units acquire automatic <varname>Before=</varname> and <varname>Conflicts=</varname> on
+ <filename>umount.target</filename> in order to be stopped during shutdown.</para></listitem>
- <listitem><para>Mount units referring to local file systems automatically gain
- an <varname>After=</varname> dependency on <filename>local-fs-pre.target</filename>.</para></listitem>
+ <listitem><para>Mount units referring to local file systems automatically gain
+ an <varname>After=</varname> dependency on <filename>local-fs-pre.target</filename>.</para></listitem>
- <listitem><para>Network mount units
- automatically acquire <varname>After=</varname> dependencies on <filename>remote-fs-pre.target</filename>,
- <filename>network.target</filename> and <filename>network-online.target</filename>. Towards the latter a
- <varname>Wants=</varname> unit is added as well.</para></listitem>
- </itemizedlist>
+ <listitem><para>Network mount units
+ automatically acquire <varname>After=</varname> dependencies on <filename>remote-fs-pre.target</filename>,
+ <filename>network.target</filename> and <filename>network-online.target</filename>. Towards the latter a
+ <varname>Wants=</varname> unit is added as well.</para></listitem>
+ </itemizedlist>
- <para>Mount units referring to local and network file systems are
- distinguished by their file system type specification. In some cases this is not sufficient (for example network
- block device based mounts, such as iSCSI), in which case <option>_netdev</option> may be added to the mount option
- string of the unit, which forces systemd to consider the mount unit a network mount.</para>
+ <para>Mount units referring to local and network file systems are distinguished by their file system type
+ specification. In some cases this is not sufficient (for example network block device based mounts, such as
+ iSCSI), in which case <option>_netdev</option> may be added to the mount option string of the unit, which forces
+ systemd to consider the mount unit a network mount.</para>
+ </refsect2>
</refsect1>
<refsect1>
@@ -325,7 +303,7 @@
<varlistentry>
<term><option>x-systemd.makefs</option></term>
- <listitem><para>The file system or swap structure will be intialized
+ <listitem><para>The file system or swap structure will be initialized
on the device. If the device is not "empty", i.e. it contains any signature,
the operation will be skipped. It is hence expected that this option
remains set even after the device has been initalized.</para>
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index af46360f49..5073258641 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.netdev" conditional='ENABLE_NETWORKD'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd.network</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -187,6 +161,8 @@
<row><entry><varname>wireguard</varname></entry>
<entry>WireGuard Secure Network Tunnel.</entry></row>
+ <row><entry><varname>netdevsim</varname></entry>
+ <entry> A simulator. This simulated networking device is used for testing various networking APIs and at this time is particularly focused on testing hardware offloading related interfaces.</entry></row>
</tbody>
</tgroup>
</table>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 80d2802610..fc8e0aea68 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.network" conditional='ENABLE_NETWORKD'>
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd.network</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -116,8 +90,12 @@
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem>
- <para>The hardware address of the interface (use full colon-delimited hexadecimal, e.g.,
- 01:23:45:67:89:ab).</para>
+ <para>A whitespace-separated list of hardware addresses. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example below.
+ This option may appear more than one, in which case the lists are merged. If the empty string is assigned to this option, the list
+ of hardware addresses defined prior to this is reset.</para>
+
+ <para>Example:
+ <programlisting>MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
@@ -243,7 +221,7 @@
<varlistentry>
<term><varname>ARP=</varname></term>
<listitem>
- <para> A boolean. Enables or disables the ARP (low-level Address Resolution Protocol)
+ <para>A boolean. Enables or disables the ARP (low-level Address Resolution Protocol)
for this interface. Defaults to unset, which means that the kernel default will be used.</para>
<para> For example, disabling ARP is useful when creating multiple MACVLAN or VLAN virtual
interfaces atop a single lower-level physical interface, which will then only serve as a
@@ -252,6 +230,19 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>Multicast=</varname></term>
+ <listitem>
+ <para>A boolean. Enables or disables the multicast flag on the device.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>AllMulticast=</varname></term>
+ <listitem>
+ <para>A boolean. When this flag is set the driver retrieves all multicast packets from the network.
+ This happens when multicast routing is enabled.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>Unmanaged=</varname></term>
<listitem>
<para>A boolean. When <literal>yes</literal>, no attempts are
@@ -381,6 +372,21 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>DNSOverTLS=</varname></term>
+ <listitem>
+ <para>Takes false or
+ <literal>opportunistic</literal>. When set to <literal>opportunistic</literal>, enables
+ <ulink
+ url="https://tools.ietf.org/html/rfc7858">DNS-over-TLS</ulink>
+ support on the link. This option defines a
+ per-interface setting for
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
+ global <varname>DNSOverTLS=</varname> option. Defaults to
+ false. This setting is read by
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>DNSSEC=</varname></term>
<listitem>
<para>A boolean or
@@ -447,7 +453,7 @@
connected bridge, <literal>non-tpmr-bridge</literal> permits propagation across Two-Port MAC Relays, but
not any other bridges, and <literal>customer-bridge</literal> permits propagation until a customer bridge
is reached. For details about these concepts, see <ulink
- url="http://standards.ieee.org/getieee802/download/802.1AB-2009.pdf">IEEE 802.1AB-2009</ulink>. Note that
+ url="https://standards.ieee.org/findstds/standard/802.1AB-2016.html">IEEE 802.1AB-2016</ulink>. Note that
configuring this setting to true is equivalent to <literal>nearest-bridge</literal>, the recommended and
most restricted level of propagation. See <varname>LLDP=</varname> above for an option to enable LLDP
reception.</para>
@@ -680,6 +686,12 @@
</para></listitem>
</varlistentry>
<varlistentry>
+ <term><varname>IPv6MTUBytes=</varname></term>
+ <listitem><para>Configures IPv6 maximum transmission unit (MTU).
+ An integer greater than or equal to 1280 bytes. Defaults to unset.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>Bridge=</varname></term>
<listitem>
<para>The name of the bridge to add the link to. See
@@ -1102,7 +1114,16 @@
</para>
</listitem>
</varlistentry>
-
+ <varlistentry>
+ <term><varname>MTUBytes=</varname></term>
+ <listitem>
+ <para>The maximum transmission unit in bytes to set for the
+ route. The usual suffixes K, M, G, are supported and are
+ understood to the base of 1024.</para>
+ <para>Note that if IPv6 is enabled on the interface, and the MTU is chosen
+ below 1280 (the minimum MTU for IPv6) it will automatically be increased to this value.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -1236,8 +1257,11 @@
<varlistentry>
<term><varname>ClientIdentifier=</varname></term>
<listitem>
- <para>The DHCPv4 client identifier to use. Either <literal>mac</literal> to use the MAC address of the link
- or <literal>duid</literal> (the default, see below) to use an RFC4361-compliant Client ID.</para>
+ <para>The DHCPv4 client identifier to use. Takes one of <literal>mac</literal>, <literal>duid</literal> or <literal>duid-only</literal>.
+ If set to <literal>mac</literal>, the MAC address of the link is used.
+ If set to <literal>duid</literal>, an RFC4361-compliant Client ID, which is the combination of IAID and DUID (see below), is used.
+ If set to <literal>duid-only</literal>, only DUID is used, this may not be RFC compliant, but some setups may require to use this.
+ Defaults to <literal>duid</literal>.</para>
</listitem>
</varlistentry>
@@ -1250,6 +1274,16 @@
</varlistentry>
<varlistentry>
+ <term><varname>UserClass=</varname></term>
+ <listitem>
+ <para>A DHCPv4 client can use UserClass option to identify the type or category of user or applications
+ it represents. The information contained in this option is a string that represents the user class of which
+ the client is a member. Each class sets an identifying string of information to be used by the DHCP
+ service to classify clients. Takes a whitespace-separated list of strings.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>DUIDType=</varname></term>
<listitem>
<para>Override the global <varname>DUIDType</varname> setting for this network. See
@@ -1379,7 +1413,6 @@
</variablelist>
</refsect1>
-
<refsect1>
<title>[DHCPServer] Section Options</title>
<para>The <literal>[DHCPServer]</literal> section contains
@@ -1639,7 +1672,7 @@
<listitem>
<para>A boolean. Controls whether the bridge should flood
traffic for which an FDB entry is missing and the destination
- is unknown through this port. Defaults to on.
+ is unknown through this port. Defaults to unset.
</para>
</listitem>
</varlistentry>
@@ -1647,7 +1680,7 @@
<term><varname>HairPin=</varname></term>
<listitem>
<para>A boolean. Configures whether traffic may be sent back
- out of the port on which it was received. By default, this
+ out of the port on which it was received. Defaults to unset. When this
flag is false, and the bridge will not forward traffic back
out of the receiving port.</para>
</listitem>
@@ -1656,7 +1689,7 @@
<term><varname>UseBPDU=</varname></term>
<listitem>
<para>A boolean. Configures whether STP Bridge Protocol Data Units will be
- processed by the bridge port. Defaults to yes.</para>
+ processed by the bridge port. Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -1664,7 +1697,7 @@
<listitem>
<para>A boolean. This flag allows the bridge to immediately stop multicast
traffic on a port that receives an IGMP Leave message. It is only used with
- IGMP snooping if enabled on the bridge. Defaults to off.</para>
+ IGMP snooping if enabled on the bridge. Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -1672,7 +1705,7 @@
<listitem>
<para>A boolean. Configures whether a given port is allowed to
become a root port. Only used when STP is enabled on the bridge.
- Defaults to on.</para>
+ Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -1722,6 +1755,39 @@
</varlistentry>
</variablelist>
</refsect1>
+
+ <refsect1>
+ <title>[CAN] Section Options</title>
+ <para>The <literal>[CAN]</literal> section manages the Controller Area Network (CAN bus) and accepts the
+ following keys.</para>
+ <variablelist class='network-directives'>
+ <varlistentry>
+ <term><varname>BitRate=</varname></term>
+ <listitem>
+ <para>The bitrate of CAN device in bits per second. The usual SI prefixes (K, M) with the base of 1000 can
+ be used here.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SamplePoint=</varname></term>
+ <listitem>
+ <para>Optional sample point in percent with one decimal (e.g. <literal>75%</literal>,
+ <literal>87.5%</literal>) or permille (e.g. <literal>875‰</literal>).</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>RestartSec=</varname></term>
+ <listitem>
+ <para>Automatic restart delay time. If set to a non-zero value, a restart of the CAN controller will be
+ triggered automatically in case of a bus-off condition after the specified delay time. Subsecond delays can
+ be specified using decimals (e.g. <literal>0.1s</literal>) or a <literal>ms</literal> or
+ <literal>us</literal> postfix. Using <literal>infinity</literal> or <literal>0</literal> will turn the
+ automatic restart off. By default automatic restart is disabled.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>[BridgeVLAN] Section Options</title>
<para>The <literal>[BridgeVLAN]</literal> section manages the VLAN ID configuration of a bridge port and accepts
diff --git a/man/systemd.nspawn.xml b/man/systemd.nspawn.xml
index 9a6a2351f8..4a263d376d 100644
--- a/man/systemd.nspawn.xml
+++ b/man/systemd.nspawn.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.nspawn">
@@ -31,15 +14,6 @@
<refentryinfo>
<title>systemd.nspawn</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -236,6 +210,17 @@
</varlistentry>
<varlistentry>
+ <term><varname>NoNewPrivileges=</varname></term>
+
+ <listitem><para>Takes a boolean argument that controls the <constant>PR_SET_NO_NEW_PRIVS</constant> flag for
+ the container payload. This is equivalent to the
+ <option>--no-new-privileges=</option> command line switch. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>KillSignal=</varname></term>
<listitem><para>Specify the process signal to send to the
@@ -291,6 +276,84 @@
details.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>LimitCPU=</varname></term>
+ <term><varname>LimitFSIZE=</varname></term>
+ <term><varname>LimitDATA=</varname></term>
+ <term><varname>LimitSTACK=</varname></term>
+ <term><varname>LimitCORE=</varname></term>
+ <term><varname>LimitRSS=</varname></term>
+ <term><varname>LimitNOFILE=</varname></term>
+ <term><varname>LimitAS=</varname></term>
+ <term><varname>LimitNPROC=</varname></term>
+ <term><varname>LimitMEMLOCK=</varname></term>
+ <term><varname>LimitLOCKS=</varname></term>
+ <term><varname>LimitSIGPENDING=</varname></term>
+ <term><varname>LimitMSGQUEUE=</varname></term>
+ <term><varname>LimitNICE=</varname></term>
+ <term><varname>LimitRTPRIO=</varname></term>
+ <term><varname>LimitRTTIME=</varname></term>
+
+ <listitem><para>Configures various types of resource limits applied to containers. This is equivalent to the
+ <option>--rlimit=</option> command line switch, and takes the same arguments. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>OOMScoreAdjust=</varname></term>
+
+ <listitem><para>Configures the OOM score adjustment value. This is equivalent to the
+ <option>--oom-score-adjust=</option> command line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>CPUAffinity=</varname></term>
+
+ <listitem><para>Configures the CPU affinity. This is equivalent to the <option>--cpu-affinity=</option> command
+ line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>Hostname=</varname></term>
+
+ <listitem><para>Configures the kernel hostname set for the container. This is equivalent to the
+ <option>--hostname=</option> command line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ResolvConf=</varname></term>
+
+ <listitem><para>Configures how <filename>/etc/resolv.conf</filename> in the container shall be handled. This is
+ equivalent to the <option>--resolv-conf=</option> command line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>Timezone=</varname></term>
+
+ <listitem><para>Configures how <filename>/etc/localtime</filename> in the container shall be handled. This is
+ equivalent to the <option>--localtime=</option> command line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>LinkJournal=</varname></term>
+
+ <listitem><para>Configures how to link host and container journal setups. This is equivalent to the
+ <option>--link-journal=</option> command line switch, and takes the same parameter. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml
index ca7d6d3c18..113d74a220 100644
--- a/man/systemd.offline-updates.xml
+++ b/man/systemd.offline-updates.xml
@@ -4,39 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.offline-updates">
<refentryinfo>
<title>systemd.offline-updates</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -163,8 +136,20 @@
<listitem>
<para>The update service should declare <varname>DefaultDependencies=false</varname>,
<varname>Requires=sysinit.target</varname>, <varname>After=sysinit.target</varname>,
+ <varname>After=system-update-pre.target</varname>
and explicitly pull in any other services it requires.</para>
</listitem>
+
+ <listitem>
+ <para>It may be desirable to always run an auxiliary unit when booting
+ into offline-updates mode, which itself does not install updates. To
+ do this create a .service file with
+ <varname>Wants=system-update-pre.target</varname> and
+ <varname>Before=system-update-pre.target</varname> and add a symlink
+ to that file under
+ <filename noindex='true'>/usr/lib/systemd/system-update.target.wants</filename>
+ .</para>
+ </listitem>
</orderedlist>
</refsect1>
diff --git a/man/systemd.path.xml b/man/systemd.path.xml
index 30f295d2d7..e513fe6d43 100644
--- a/man/systemd.path.xml
+++ b/man/systemd.path.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.path">
<refentryinfo>
<title>systemd.path</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -84,36 +58,40 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
+ <title>Automatic Dependencies</title>
- <para>The following dependencies are implicitly added:</para>
+ <refsect2>
+ <title>Implicit Dependencies</title>
- <itemizedlist>
- <listitem><para>If a path unit is beneath another mount unit in the file
- system hierarchy, both a requirement and an ordering dependency
- between both units are created automatically.</para></listitem>
+ <para>The following dependencies are implicitly added:</para>
- <listitem><para>An implicit <varname>Before=</varname> dependency is added
- between a path unit and the unit it is supposed to activate.</para></listitem>
- </itemizedlist>
- </refsect1>
+ <itemizedlist>
+ <listitem><para>If a path unit is beneath another mount unit in the file
+ system hierarchy, both a requirement and an ordering dependency
+ between both units are created automatically.</para></listitem>
- <refsect1>
- <title>Default Dependencies</title>
+ <listitem><para>An implicit <varname>Before=</varname> dependency is added
+ between a path unit and the unit it is supposed to activate.</para></listitem>
+ </itemizedlist>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
- <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
+ <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
- <itemizedlist>
- <listitem><para>Path units will automatically have dependencies of type <varname>Before=</varname> on
- <filename>paths.target</filename>,
- dependencies of type <varname>After=</varname> and <varname>Requires=</varname> on
- <filename>sysinit.target</filename>, and have dependencies of type <varname>Conflicts=</varname> and
- <varname>Before=</varname> on <filename>shutdown.target</filename>. These ensure that path units are terminated
- cleanly prior to system shutdown. Only path units involved with early boot or late system shutdown should
- disable <varname>DefaultDependencies=</varname> option.</para></listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem><para>Path units will automatically have dependencies of type <varname>Before=</varname> on
+ <filename>paths.target</filename>,
+ dependencies of type <varname>After=</varname> and <varname>Requires=</varname> on
+ <filename>sysinit.target</filename>, and have dependencies of type <varname>Conflicts=</varname> and
+ <varname>Before=</varname> on <filename>shutdown.target</filename>. These ensure that path units are terminated
+ cleanly prior to system shutdown. Only path units involved with early boot or late system shutdown should
+ disable <varname>DefaultDependencies=</varname> option.</para></listitem>
+ </itemizedlist>
- <para></para>
+ <para></para>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd.preset.xml b/man/systemd.preset.xml
index 7b978f7915..cf807bd4c8 100644
--- a/man/systemd.preset.xml
+++ b/man/systemd.preset.xml
@@ -3,38 +3,12 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
<refentry id="systemd.preset">
<refentryinfo>
<title>systemd.preset</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index 5033802c85..370c110592 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<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>
diff --git a/man/systemd.scope.xml b/man/systemd.scope.xml
index 1128d236ce..cc0345abac 100644
--- a/man/systemd.scope.xml
+++ b/man/systemd.scope.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<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>
@@ -77,29 +51,33 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
-
- <para>Implicit dependencies may be added as result of
- resource control parameters as documented in
- <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
- </refsect1>
-
- <refsect1>
- <title>Default Dependencies</title>
-
- <para>The following dependencies are added unless
- <varname>DefaultDependencies=no</varname> is set:</para>
-
- <itemizedlist>
- <listitem><para>Scope units will automatically 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
- <varname>DefaultDependencies=</varname> option.</para></listitem>
- </itemizedlist>
+ <title>Automatic Dependencies</title>
+
+ <refsect2>
+ <title>Implicit Dependencies</title>
+
+ <para>Implicit dependencies may be added as result of
+ resource control parameters as documented in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
+
+ <para>The following dependencies are added unless
+ <varname>DefaultDependencies=no</varname> is set:</para>
+
+ <itemizedlist>
+ <listitem><para>Scope units will automatically 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
+ <varname>DefaultDependencies=</varname> option.</para></listitem>
+ </itemizedlist>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index b68d351dff..add54524ce 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.service">
<refentryinfo>
<title>systemd.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>
@@ -91,55 +65,73 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
-
- <para>The following dependencies are implicitly added:</para>
-
- <itemizedlist>
- <listitem><para>Services with <varname>Type=dbus</varname> set automatically
- acquire dependencies of type <varname>Requires=</varname> and
- <varname>After=</varname> on
- <filename>dbus.socket</filename>.</para></listitem>
-
- <listitem><para>Socket activated services are automatically ordered after
- their activating <filename>.socket</filename> units via an
- automatic <varname>After=</varname> dependency.
- Services also pull in all <filename>.socket</filename> units
- listed in <varname>Sockets=</varname> via automatic
- <varname>Wants=</varname> and <varname>After=</varname> dependencies.</para></listitem>
- </itemizedlist>
-
- <para>Additional implicit dependencies may be added as result of
- execution and resource control parameters as documented in
- <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- and
- <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ <title>Service Templates</title>
+
+ <para>It is possible for <command>systemd</command> services to take a single argument via the
+ <literal><replaceable>service</replaceable>@<replaceable>argument</replaceable>.service</literal>
+ syntax. Such services are called "instantiated" services, while the unit definition without the
+ <replaceable>argument</replaceable> parameter is called a "template". An example could be a
+ <filename>dhcpcd@.service</filename> service template which takes a network interface as a
+ parameter to form an instantiated service. Within the service file, this parameter or "instance
+ name" can be accessed with %-specifiers. See
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details.</para>
</refsect1>
<refsect1>
- <title>Default Dependencies</title>
-
- <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
-
- <itemizedlist>
- <listitem><para>Service units will have dependencies of type <varname>Requires=</varname> and
- <varname>After=</varname> on <filename>sysinit.target</filename>, a dependency of type <varname>After=</varname> on
- <filename>basic.target</filename> as well as dependencies of type <varname>Conflicts=</varname> and
- <varname>Before=</varname> on <filename>shutdown.target</filename>. These ensure that normal service units pull in
- basic system initialization, and are terminated cleanly prior to system shutdown. Only services involved with early
- boot or late system shutdown should disable this option.</para></listitem>
-
- <listitem><para>Instanced service units (i.e. service units with an <literal>@</literal> in their name) are assigned by
- default a per-template slice unit (see
- <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>), named after the
- template unit, containing all instances of the specific template. This slice is normally stopped at shutdown,
- together with all template instances. If that is not desired, set <varname>DefaultDependencies=no</varname> in the
- template unit, and either define your own per-template slice unit file that also sets
- <varname>DefaultDependencies=no</varname>, or set <varname>Slice=system.slice</varname> (or another suitable slice)
- in the template unit. Also see
- <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- </para></listitem>
- </itemizedlist>
+ <title>Automatic Dependencies</title>
+
+ <refsect2>
+ <title>Implicit Dependencies</title>
+
+ <para>The following dependencies are implicitly added:</para>
+
+ <itemizedlist>
+ <listitem><para>Services with <varname>Type=dbus</varname> set automatically
+ acquire dependencies of type <varname>Requires=</varname> and
+ <varname>After=</varname> on
+ <filename>dbus.socket</filename>.</para></listitem>
+
+ <listitem><para>Socket activated services are automatically ordered after
+ their activating <filename>.socket</filename> units via an
+ automatic <varname>After=</varname> dependency.
+ Services also pull in all <filename>.socket</filename> units
+ listed in <varname>Sockets=</varname> via automatic
+ <varname>Wants=</varname> and <varname>After=</varname> dependencies.</para></listitem>
+ </itemizedlist>
+
+ <para>Additional implicit dependencies may be added as result of
+ execution and resource control parameters as documented in
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
+
+ <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
+
+ <itemizedlist>
+ <listitem><para>Service units will have dependencies of type <varname>Requires=</varname> and
+ <varname>After=</varname> on <filename>sysinit.target</filename>, a dependency of type <varname>After=</varname> on
+ <filename>basic.target</filename> as well as dependencies of type <varname>Conflicts=</varname> and
+ <varname>Before=</varname> on <filename>shutdown.target</filename>. These ensure that normal service units pull in
+ basic system initialization, and are terminated cleanly prior to system shutdown. Only services involved with early
+ boot or late system shutdown should disable this option.</para></listitem>
+
+ <listitem><para>Instanced service units (i.e. service units with an <literal>@</literal> in their name) are assigned by
+ default a per-template slice unit (see
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>), named after the
+ template unit, containing all instances of the specific template. This slice is normally stopped at shutdown,
+ together with all template instances. If that is not desired, set <varname>DefaultDependencies=no</varname> in the
+ template unit, and either define your own per-template slice unit file that also sets
+ <varname>DefaultDependencies=no</varname>, or set <varname>Slice=system.slice</varname> (or another suitable slice)
+ in the template unit. Also see
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </itemizedlist>
+ </refsect2>
</refsect1>
<refsect1>
@@ -301,8 +293,9 @@
<varname>ExecStop=</varname> line set. (Services lacking both <varname>ExecStart=</varname> and
<varname>ExecStop=</varname> are not valid.)</para>
- <para>For each of the specified commands, the first argument must be an absolute path to an
- executable. Optionally, this filename may be prefixed with a number of special characters:</para>
+ <para>For each of the specified commands, the first argument must be either an absolute path to an executable
+ or a simple file name without any slashes. Optionally, this filename may be prefixed with a number of special
+ characters:</para>
<table>
<title>Special executable prefixes</title>
@@ -336,7 +329,7 @@
<row>
<entry><literal>!</literal></entry>
- <entry>Similar to the <literal>+</literal> character discussed above this permits invoking command lines with elevated privileges. However, unlike <literal>+</literal> the <literal>!</literal> character exclusively alters the effect of <varname>User=</varname>, <varname>Group=</varname> and <varname>SupplementaryGroups=</varname>, i.e. only the stanzas the affect user and group credentials. Note that this setting may be combined with <varname>DynamicUser=</varname>, in which case a dynamic user/group pair is allocated before the command is invoked, but credential changing is left to the executed process itself.</entry>
+ <entry>Similar to the <literal>+</literal> character discussed above this permits invoking command lines with elevated privileges. However, unlike <literal>+</literal> the <literal>!</literal> character exclusively alters the effect of <varname>User=</varname>, <varname>Group=</varname> and <varname>SupplementaryGroups=</varname>, i.e. only the stanzas that affect user and group credentials. Note that this setting may be combined with <varname>DynamicUser=</varname>, in which case a dynamic user/group pair is allocated before the command is invoked, but credential changing is left to the executed process itself.</entry>
</row>
<row>
@@ -529,12 +522,12 @@
<varlistentry>
<term><varname>TimeoutStopSec=</varname></term>
- <listitem><para>Configures the time to wait for stop. If a
- service is asked to stop, but does not terminate in the
- specified time, it will be terminated forcibly via
- <constant>SIGTERM</constant>, and after another timeout of
- equal duration with <constant>SIGKILL</constant> (see
- <varname>KillMode=</varname> in
+ <listitem><para>This option serves two purposes. First, it configures the time to wait for each
+ <constant>ExecStop=</constant> command. If any of them times out, subsequent <constant>ExecStop=</constant> commands
+ are skipped and the service will be terminated by <constant>SIGTERM</constant>. If no <constant>ExecStop=</constant>
+ commands are specified, the service gets the <constant>SIGTERM</constant> immediately. Second, it configures the time
+ to wait for the service itself to stop. If it doesn't terminate in the specified time, it will be forcibly terminated
+ by <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 time span value such
as "5min 20s". Pass <literal>infinity</literal> to disable the
@@ -575,7 +568,7 @@
must occur before <varname>RuntimeMaxSec=</varname> is exceeded, and once the runtime has exended beyond
<varname>RuntimeMaxSec=</varname>, the service manager will allow the service to continue to run, provided
the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified until the service
- shutdown is acheived by <literal>STOPPING=1</literal> (or termination). (see
+ shutdown is achieved by <literal>STOPPING=1</literal> (or termination). (see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
</para></listitem>
</varlistentry>
@@ -931,7 +924,10 @@
passed to the service manager from a specific service are passed back to the service's main process on the next
service restart. Any file descriptors passed to the service manager are automatically closed when
<constant>POLLHUP</constant> or <constant>POLLERR</constant> is seen on them, or when the service is fully
- stopped and no job is queued or being executed for it.</para></listitem>
+ stopped and no job is queued or being executed for it. If this option is used, <varname>NotifyAccess=</varname>
+ (see above) 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></listitem>
</varlistentry>
<varlistentry>
@@ -1004,11 +1000,9 @@
<literal>&amp;</literal>, and <emphasis>other elements of shell
syntax are not supported</emphasis>.</para>
- <para>The command to execute must be an absolute path name. It may
- contain spaces, but control characters are not allowed.</para>
+ <para>The command to execute may contain spaces, but control characters are not allowed.</para>
- <para>The command line accepts <literal>%</literal> specifiers as
- described in
+ <para>The command line accepts <literal>%</literal> specifiers as described in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>Basic environment variable substitution is supported. Use
@@ -1022,10 +1016,21 @@
For this type of expansion, quotes are respected when splitting
into words, and afterwards removed.</para>
+ <para>If the command is not a full (absolute) path, it will be resolved to a full path using a
+ fixed search path determinted at compilation time. Searched directories include
+ <filename>/usr/local/bin/</filename>, <filename>/usr/bin/</filename>, <filename>/bin/</filename>
+ on systems using split <filename>/usr/bin/</filename> and <filename>/bin/</filename>
+ directories, and their <filename>sbin/</filename> counterparts on systems using split
+ <filename>bin/</filename> and <filename>sbin/</filename>. It is thus safe to use just the
+ executable name in case of executables located in any of the "standard" directories, and an
+ absolute path must be used in other cases. Using an absolute path is recommended to avoid
+ ambiguity. Hint: this search path may be queried using
+ <command>systemd-path search-binaries-default</command>.</para>
+
<para>Example:</para>
<programlisting>Environment="ONE=one" 'TWO=two two'
-ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
+ExecStart=echo $ONE $TWO ${TWO}</programlisting>
<para>This will execute <command>/bin/echo</command> with four
arguments: <literal>one</literal>, <literal>two</literal>,
@@ -1035,7 +1040,7 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
<programlisting>Environment=ONE='one' "TWO='two two' too" THREE=
ExecStart=/bin/echo ${ONE} ${TWO} ${THREE}
ExecStart=/bin/echo $ONE $TWO $THREE</programlisting>
- <para>This results in <filename>echo</filename> being
+ <para>This results in <filename>/bin/echo</filename> being
called twice, the first time with arguments
<literal>'one'</literal>,
<literal>'two two' too</literal>, <literal></literal>,
@@ -1061,27 +1066,27 @@ ExecStart=/bin/echo $ONE $TWO $THREE</programlisting>
<para>Note that shell command lines are not directly supported. If
shell command lines are to be used, they need to be passed
explicitly to a shell implementation of some kind. Example:</para>
- <programlisting>ExecStart=/bin/sh -c 'dmesg | tac'</programlisting>
+ <programlisting>ExecStart=sh -c 'dmesg | tac'</programlisting>
<para>Example:</para>
- <programlisting>ExecStart=/bin/echo one ; /bin/echo "two two"</programlisting>
+ <programlisting>ExecStart=echo one ; echo "two two"</programlisting>
- <para>This will execute <command>/bin/echo</command> two times,
+ <para>This will execute <command>echo</command> two times,
each time with one argument: <literal>one</literal> and
<literal>two two</literal>, respectively. Because two commands are
specified, <varname>Type=oneshot</varname> must be used.</para>
<para>Example:</para>
- <programlisting>ExecStart=/bin/echo / &gt;/dev/null &amp; \; \
-/bin/ls</programlisting>
+ <programlisting>ExecStart=echo / &gt;/dev/null &amp; \; \
+ls</programlisting>
- <para>This will execute <command>/bin/echo</command>
+ <para>This will execute <command>echo</command>
with five arguments: <literal>/</literal>,
<literal>&gt;/dev/null</literal>,
<literal>&amp;</literal>, <literal>;</literal>, and
- <literal>/bin/ls</literal>.</para>
+ <literal>ls</literal>.</para>
<table>
<title>C escapes supported in command lines and environment variables</title>
diff --git a/man/systemd.slice.xml b/man/systemd.slice.xml
index d67cce102a..37bee0ea4c 100644
--- a/man/systemd.slice.xml
+++ b/man/systemd.slice.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<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>
@@ -98,29 +72,33 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
+ <title>Automatic Dependencies</title>
- <para>The following dependencies are implicitly added:</para>
+ <refsect2>
+ <title>Implicit Dependencies</title>
- <itemizedlist>
- <listitem><para>Slice units automatically gain dependencies of type
- <varname>After=</varname> and <varname>Requires=</varname> on
- their immediate parent slice unit.</para></listitem>
- </itemizedlist>
- </refsect1>
+ <para>The following dependencies are implicitly added:</para>
- <refsect1>
- <title>Default Dependencies</title>
+ <itemizedlist>
+ <listitem><para>Slice units automatically gain dependencies of type
+ <varname>After=</varname> and <varname>Requires=</varname> on
+ their immediate parent slice unit.</para></listitem>
+ </itemizedlist>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
- <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
+ <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
- <itemizedlist>
- <listitem><para>Slice units will automatically 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 late system shutdown should disable
- <varname>DefaultDependencies=</varname> option.</para></listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem><para>Slice units will automatically 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 late system shutdown should disable
+ <varname>DefaultDependencies=</varname> option.</para></listitem>
+ </itemizedlist>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
index a2b5ac0b59..5fd6c1598f 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.socket">
<refentryinfo>
<title>systemd.socket</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -123,53 +97,57 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
-
- <para>The following dependencies are implicitly added:</para>
-
- <itemizedlist>
- <listitem><para>Socket units automatically gain a <varname>Before=</varname>
- dependency on the service units they activate.</para></listitem>
-
- <listitem><para>Socket units referring to file system paths (such as AF_UNIX
- sockets or FIFOs) implicitly gain <varname>Requires=</varname> and
- <varname>After=</varname> dependencies on all mount units
- necessary to access those paths.</para></listitem>
-
- <listitem><para>Socket units using the <varname>BindToDevice=</varname>
- setting automatically gain a <varname>BindsTo=</varname> and
- <varname>After=</varname> dependency on the device unit
- encapsulating the specified network interface.</para></listitem>
- </itemizedlist>
-
- <para>Additional implicit dependencies may be added as result of
- execution and resource control parameters as documented in
- <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- and
- <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
- </refsect1>
-
- <refsect1>
- <title>Default Dependencies</title>
-
- <para>The following dependencies are added unless
- <varname>DefaultDependencies=no</varname> is set:</para>
-
- <itemizedlist>
- <listitem><para>Socket units automatically gain a
- <varname>Before=</varname> dependency on
- <filename>sockets.target</filename>.</para></listitem>
-
- <listitem><para>Socket units automatically gain a pair of
- <varname>After=</varname> and <varname>Requires=</varname>
- dependency on <filename>sysinit.target</filename>, and a pair of
- <varname>Before=</varname> and <varname>Conflicts=</varname>
- dependencies on <filename>shutdown.target</filename>. These
- dependencies ensure that the socket unit is started before normal
- services at boot, and is stopped on shutdown. Only sockets
- involved with early boot or late system shutdown should disable
- <varname>DefaultDependencies=</varname> option.</para></listitem>
- </itemizedlist>
+ <title>Automatic Dependencies</title>
+
+ <refsect2>
+ <title>Implicit Dependencies</title>
+
+ <para>The following dependencies are implicitly added:</para>
+
+ <itemizedlist>
+ <listitem><para>Socket units automatically gain a <varname>Before=</varname>
+ dependency on the service units they activate.</para></listitem>
+
+ <listitem><para>Socket units referring to file system paths (such as AF_UNIX
+ sockets or FIFOs) implicitly gain <varname>Requires=</varname> and
+ <varname>After=</varname> dependencies on all mount units
+ necessary to access those paths.</para></listitem>
+
+ <listitem><para>Socket units using the <varname>BindToDevice=</varname>
+ setting automatically gain a <varname>BindsTo=</varname> and
+ <varname>After=</varname> dependency on the device unit
+ encapsulating the specified network interface.</para></listitem>
+ </itemizedlist>
+
+ <para>Additional implicit dependencies may be added as result of
+ execution and resource control parameters as documented in
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
+
+ <para>The following dependencies are added unless
+ <varname>DefaultDependencies=no</varname> is set:</para>
+
+ <itemizedlist>
+ <listitem><para>Socket units automatically gain a
+ <varname>Before=</varname> dependency on
+ <filename>sockets.target</filename>.</para></listitem>
+
+ <listitem><para>Socket units automatically gain a pair of
+ <varname>After=</varname> and <varname>Requires=</varname>
+ dependency on <filename>sysinit.target</filename>, and a pair of
+ <varname>Before=</varname> and <varname>Conflicts=</varname>
+ dependencies on <filename>shutdown.target</filename>. These
+ dependencies ensure that the socket unit is started before normal
+ services at boot, and is stopped on shutdown. Only sockets
+ involved with early boot or late system shutdown should disable
+ <varname>DefaultDependencies=</varname> option.</para></listitem>
+ </itemizedlist>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd.special.xml b/man/systemd.special.xml
index 5bb279333c..fb12805fff 100644
--- a/man/systemd.special.xml
+++ b/man/systemd.special.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.special">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd.special</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -65,6 +39,7 @@
<filename>halt.target</filename>,
<filename>hibernate.target</filename>,
<filename>hybrid-sleep.target</filename>,
+ <filename>suspend-then-hibernate.target</filename>,
<filename>initrd-fs.target</filename>,
<filename>initrd-root-device.target</filename>,
<filename>initrd-root-fs.target</filename>,
@@ -103,6 +78,7 @@
<filename>swap.target</filename>,
<filename>sysinit.target</filename>,
<filename>system-update.target</filename>,
+ <filename>system-update-pre.target</filename>,
<filename>time-sync.target</filename>,
<filename>timers.target</filename>,
<filename>umount.target</filename>,
@@ -308,6 +284,15 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><filename>suspend-then-hibernate.target</filename></term>
+ <listitem>
+ <para>A special target unit for suspending the system for a period
+ of time, waking it and putting it into hibernate. This pulls in
+ <filename>sleep.target</filename>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><filename>halt.target</filename></term>
<listitem>
<para>A special target unit for shutting down and halting
@@ -674,6 +659,7 @@
</varlistentry>
<varlistentry>
<term><filename>system-update.target</filename></term>
+ <term><filename>system-update-pre.target</filename></term>
<term><filename>system-update-cleanup.service</filename></term>
<listitem>
<para>A special target unit that is used for offline system updates.
@@ -683,12 +669,13 @@
<citerefentry><refentrytitle>systemd.offline-updates</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
- <para>Updates should happen before the <filename>system-update.target</filename> is
- reached, and the services which implement them should cause the machine to reboot. As
- a safety measure, if this does not happen, and <filename>/system-update</filename>
- still exists after <filename>system-update.target</filename> is reached,
- <filename>system-update-cleanup.service</filename> will remove this symlink and
- reboot the machine.</para>
+ <para>Updates should happen before the <filename>system-update.target</filename> is reached, and the services
+ which implement them should cause the machine to reboot. The main units executing the update should order
+ themselves after <filename>system-update-pre.target</filename> but not pull it in. Services which want to run
+ during system updates only, but before the actual system update is executed should order themselves before
+ this unit and pull it in. As a safety measure, if this does not happen, and
+ <filename>/system-update</filename> still exists after <filename>system-update.target</filename> is reached,
+ <filename>system-update-cleanup.service</filename> will remove this symlink and reboot the machine.</para>
</listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml
index acedb9fb25..998a047ec5 100644
--- a/man/systemd.swap.xml
+++ b/man/systemd.swap.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.swap">
<refentryinfo>
<title>systemd.swap</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -89,34 +63,38 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
-
- <para>The following dependencies are implicitly added:</para>
-
- <itemizedlist>
- <listitem><para>All swap units automatically get the
- <varname>BindsTo=</varname> and <varname>After=</varname>
- dependencies on the device units or the mount units of the files
- they are activated from.</para></listitem>
- </itemizedlist>
-
- <para>Additional implicit dependencies may be added as result of
- execution and resource control parameters as documented in
- <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- and
- <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
- </refsect1>
-
- <refsect1>
- <title>Default Dependencies</title>
-
- <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
-
- <itemizedlist>
- <listitem><para>Swap units automatically acquire a <varname>Conflicts=</varname> and a
- <varname>Before=</varname> dependency on <filename>umount.target</filename> so that they are deactivated at
- shutdown as well as a <varname>Before=swap.target</varname> dependency.</para></listitem>
- </itemizedlist>
+ <title>Automatic Dependencies</title>
+
+ <refsect2>
+ <title>Implicit Dependencies</title>
+
+ <para>The following dependencies are implicitly added:</para>
+
+ <itemizedlist>
+ <listitem><para>All swap units automatically get the
+ <varname>BindsTo=</varname> and <varname>After=</varname>
+ dependencies on the device units or the mount units of the files
+ they are activated from.</para></listitem>
+ </itemizedlist>
+
+ <para>Additional implicit dependencies may be added as result of
+ execution and resource control parameters as documented in
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
+
+ <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
+
+ <itemizedlist>
+ <listitem><para>Swap units automatically acquire a <varname>Conflicts=</varname> and a
+ <varname>Before=</varname> dependency on <filename>umount.target</filename> so that they are deactivated at
+ shutdown as well as a <varname>Before=swap.target</varname> dependency.</para></listitem>
+ </itemizedlist>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd.syntax.xml b/man/systemd.syntax.xml
new file mode 100644
index 0000000000..448ae174cb
--- /dev/null
+++ b/man/systemd.syntax.xml
@@ -0,0 +1,98 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
+<!ENTITY % entities SYSTEM "custom-entities.ent" >
+%entities;
+]>
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="systemd.syntax">
+
+ <refentryinfo>
+ <title>systemd.syntax</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd.syntax</refentrytitle>
+ <manvolnum>7</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd.syntax</refname>
+ <refpurpose>General syntax of systemd configuration files</refpurpose>
+ </refnamediv>
+
+ <refsect1>
+ <title>Introduction</title>
+
+ <para>This page describes the basic principles of configuration files used by
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ and related programs for:
+ <itemizedlist>
+ <listitem><para>systemd unit files, see
+ <citerefentry><refentrytitle>systemd.unit</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.device</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.automount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.path</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry></para></listitem>
+
+ <listitem><para>daemon config files, see
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-user.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journal-upload.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-sleep.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>timesyncd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>The syntax is inspired by
+ <ulink url="http://standards.freedesktop.org/desktop-entry-spec/latest/">XDG Desktop Entry Specification</ulink>
+ <filename>.desktop</filename> files, which are in turn inspired by Microsoft Windows
+ <filename>.ini</filename> files.
+ </para>
+
+ <para>Each file is a plain text file divided into sections, with configuration entries in the
+ style <replaceable>key</replaceable>=<replaceable>value</replaceable>.
+ Empty lines and lines starting with <literal>#</literal> or <literal>;</literal> are
+ ignored, which may be used for commenting.</para>
+
+ <para>Lines ending in a backslash are concatenated with the following line while reading and the
+ backslash is replaced by a space character. This may be used to wrap long lines. The limit on
+ line length is very large (currently 1 MB), but it is recommended to avoid such long lines and
+ use multiple directives, variable substitution, or other mechanism as appropriate for the given
+ file type.</para>
+
+ <example><programlisting>[Section A]
+KeyOne=value 1
+KeyTwo=value 2
+
+# a comment
+
+[Section B]
+Setting="something" "some thing" "…"
+KeyTwo=value 2 \
+ value 2 continued
+</programlisting></example>
+
+ <para>Various settings are allowed to be specified more than once, in which case the
+ interpretation depends on the setting. Often, multiple settings form a list, and setting to an
+ empty value "resets", which means that previous assignments are ignored. When this is allowed,
+ it is mentioned in the description of the setting. Note that using multiple assignments to the
+ same value makes the file incompatible with parsers for the XDG <filename>.desktop</filename>
+ file format.</para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd.target.xml b/man/systemd.target.xml
index 4daa9f52fd..51c5ea9af9 100644
--- a/man/systemd.target.xml
+++ b/man/systemd.target.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.target">
<refentryinfo>
<title>systemd.target</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -82,30 +56,34 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
-
- <para>There are no implicit dependencies for target units.</para>
- </refsect1>
-
- <refsect1>
- <title>Default Dependencies</title>
-
- <para>The following dependencies are added unless
- <varname>DefaultDependencies=no</varname> is set:</para>
-
- <itemizedlist>
- <listitem><para>Target units will automatically complement all
- configured dependencies of type <varname>Wants=</varname> or
- <varname>Requires=</varname> with dependencies of type
- <varname>After=</varname> unless <varname>DefaultDependencies=no</varname>
- is set in the specified units. Note that <varname>Wants=</varname> or
- <varname>Requires=</varname> must be defined in the target unit itself — if
- you for example define <varname>Wants=</varname>some.target in
- some.service, the automatic ordering will not be added.</para></listitem>
-
- <listitem><para>Target units automatically gain <varname>Conflicts=</varname>
- dependency against <filename>shutdown.target</filename>.</para></listitem>
- </itemizedlist>
+ <title>Automatic Dependencies</title>
+
+ <refsect2>
+ <title>Implicit Dependencies</title>
+
+ <para>There are no implicit dependencies for target units.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
+
+ <para>The following dependencies are added unless
+ <varname>DefaultDependencies=no</varname> is set:</para>
+
+ <itemizedlist>
+ <listitem><para>Target units will automatically complement all
+ configured dependencies of type <varname>Wants=</varname> or
+ <varname>Requires=</varname> with dependencies of type
+ <varname>After=</varname> unless <varname>DefaultDependencies=no</varname>
+ is set in the specified units. Note that <varname>Wants=</varname> or
+ <varname>Requires=</varname> must be defined in the target unit itself — if
+ you for example define <varname>Wants=</varname>some.target in
+ some.service, the automatic ordering will not be added.</para></listitem>
+
+ <listitem><para>Target units automatically gain <varname>Conflicts=</varname>
+ dependency against <filename>shutdown.target</filename>.</para></listitem>
+ </itemizedlist>
+ </refsect2>
</refsect1>
<refsect1>
diff --git a/man/systemd.time.xml b/man/systemd.time.xml
index 6cb32f13b7..ad78b611a1 100644
--- a/man/systemd.time.xml
+++ b/man/systemd.time.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.time">
@@ -28,15 +11,6 @@
<refentryinfo>
<title>systemd.time</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
index 5b1bc8b521..44b257c745 100644
--- a/man/systemd.timer.xml
+++ b/man/systemd.timer.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.timer">
<refentryinfo>
<title>systemd.timer</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -95,23 +69,33 @@
</refsect1>
<refsect1>
- <title>Default Dependencies</title>
+ <title>Automatic Dependencies</title>
- <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
+ <refsect2>
+ <title>Implicit Dependencies</title>
- <itemizedlist>
- <listitem><para>Timer units will automatically have dependencies of type <varname>Requires=</varname> and
- <varname>After=</varname> on <filename>sysinit.target</filename>, a dependency of type <varname>Before=</varname>
- on <filename>timers.target</filename>, as well as <varname>Conflicts=</varname> and <varname>Before=</varname> on
- <filename>shutdown.target</filename> to ensure that they are stopped cleanly prior to system shutdown. Only timer
- units involved with early boot or late system shutdown should disable the
- <varname>DefaultDependencies=</varname> option.</para></listitem>
-
- <listitem><para>Timer units
- with at least one <varname>OnCalendar=</varname> directive will have an additional <varname>After=</varname>
- dependency on <filename>time-sync.target</filename> to avoid being started before the system clock has been
- correctly set.</para></listitem>
- </itemizedlist>
+ <para>There are no implicit dependencies for timer units.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
+
+ <para>The following dependencies are added unless <varname>DefaultDependencies=no</varname> is set:</para>
+
+ <itemizedlist>
+ <listitem><para>Timer units will automatically have dependencies of type <varname>Requires=</varname> and
+ <varname>After=</varname> on <filename>sysinit.target</filename>, a dependency of type <varname>Before=</varname>
+ on <filename>timers.target</filename>, as well as <varname>Conflicts=</varname> and <varname>Before=</varname> on
+ <filename>shutdown.target</filename> to ensure that they are stopped cleanly prior to system shutdown. Only timer
+ units involved with early boot or late system shutdown should disable the
+ <varname>DefaultDependencies=</varname> option.</para></listitem>
+
+ <listitem><para>Timer units
+ with at least one <varname>OnCalendar=</varname> directive will have an additional <varname>After=</varname>
+ dependency on <filename>time-sync.target</filename> to avoid being started before the system clock has been
+ correctly set.</para></listitem>
+ </itemizedlist>
+ </refsect2>
</refsect1>
<refsect1>
@@ -266,7 +250,6 @@
suffix.</para></listitem>
</varlistentry>
-
<varlistentry>
<term><varname>Persistent=</varname></term>
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 0c11119707..7605c43375 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd.unit">
@@ -31,15 +14,6 @@
<refentryinfo>
<title>systemd.unit</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -96,18 +70,13 @@
<refsect1>
<title>Description</title>
- <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 watched file system
- path, a timer controlled and supervised by
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- 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 inspired by Microsoft Windows
- <filename>.ini</filename> files.</para>
+ <para>A unit file is a plain text ini-style file that 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 watched file system path, a timer controlled and supervised by
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, a
+ resource management slice or a group of externally created processes. See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
<para>This man page lists the common configuration options of all
the unit types. These options need to be configured in the [Unit]
@@ -130,18 +99,17 @@
<citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
- <para>Various settings are allowed to be specified more than once,
- in which case the interpretation depends on the setting. Often,
- multiple settings form a list, and setting to an empty value
- "resets", which means that previous assignments are ignored. When
- this is allowed, it is mentioned in the description of the
- setting. Note that using multiple assignments to the same value
- makes the unit file incompatible with parsers for the XDG
- <filename>.desktop</filename> file format.</para>
-
<para>Unit files are loaded from a set of paths determined during
compilation, described in the next section.</para>
+ <para>Unit files can be parameterized by a single argument called the "instance name". The unit
+ is then constructed based on a "template file" which serves as the definition of multiple
+ services or other units. A template unit must have a single <literal>@</literal> at the end of
+ the name (right before the type suffix). The name of the full unit is formed by inserting the
+ instance name between <literal>@</literal> and the unit type suffix. In the unit file itself,
+ the instance parameter may be referred to using <literal>%i</literal> and other specifiers, see
+ below.</para>
+
<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 continue loading the unit. If an
@@ -167,11 +135,6 @@
<literal>w</literal>, <literal>ms</literal>, <literal>us</literal>. For details see
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
- <para>Empty lines and lines starting with <literal>#</literal> or <literal>;</literal> are
- ignored. This may be used for commenting. Lines ending in a backslash are concatenated with the
- following line while reading and the backslash is replaced by a space character. This may be
- used to wrap long lines.</para>
-
<para>Units can be aliased (have an alternative name), by creating a symlink from the new name
to the existing name in one of the unit search paths. For example,
<filename>systemd-networkd.service</filename> has the alias
@@ -202,15 +165,24 @@
suffix is <filename>.requires/</filename> in this case.</para>
<para>Along with a unit file <filename>foo.service</filename>, a "drop-in" directory
- <filename>foo.service.d/</filename> may exist. All 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 for a unit, without having to
- modify unit files. Each drop-in file must have appropriate section headers. Note that for
- instantiated units, this logic will first look for the instance <literal>.d/</literal>
- subdirectory and read its <literal>.conf</literal> files, followed by the template
- <literal>.d/</literal> subdirectory and the <literal>.conf</literal> files there.</para>
-
- <para>In addition to <filename>/etc/systemd/system</filename>, the drop-in <literal>.d</literal>
+ <filename>foo.service.d/</filename> may exist. All files with the suffix <literal>.conf</literal> from this
+ directory will be parsed after the unit file itself is parsed. This is useful to alter or add configuration
+ settings for a unit, without having to modify unit files. Drop-in files must contain appropriate section
+ headers. For instantiated units, this logic will first look for the instance <literal>.d/</literal> subdirectory
+ (e.g. <literal>foo@bar.service.d/</literal>) and read its <literal>.conf</literal> files, followed by the template
+ <literal>.d/</literal> subdirectory (e.g. <literal>foo@.service.d/</literal>) and the <literal>.conf</literal>
+ files there. Moreover for units names containing dashes (<literal>-</literal>), the set of directories generated by
+ truncating the unit name after all dashes is searched too. Specifically, for a unit name
+ <filename>foo-bar-baz.service</filename> not only the regular drop-in directory
+ <filename>foo-bar-baz.service.d/</filename> is searched but also both <filename>foo-bar-.service.d/</filename> and
+ <filename>foo-.service.d/</filename>. This is useful for defining common drop-ins for a set of related units, whose
+ names begin with a common prefix. This scheme is particularly useful for mount, automount and slice units, whose
+ systematic naming structure is built around dashes as component separators. Note that equally named drop-in files
+ further down the prefix hierarchy override those further up,
+ i.e. <filename>foo-bar-.service.d/10-override.conf</filename> overrides
+ <filename>foo-.service.d/10-override.conf</filename>.</para>
+
+ <para>In addition to <filename>/etc/systemd/system</filename>, the drop-in <literal>.d/</literal>
directories for system services can be placed in <filename>/usr/lib/systemd/system</filename> or
<filename>/run/systemd/system</filename> directories. Drop-in files in <filename>/etc</filename>
take precedence over those in <filename>/run</filename> which in turn take precedence over those
@@ -227,21 +199,15 @@
socket-based activation which make dependencies implicit,
resulting in a both simpler and more flexible system.</para>
- <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
- first search for the literal unit name in the
- file system. If that yields no success and the unit
- 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 <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
- for <filename>getty@.service</filename> and
- instantiate a service from that configuration file if
- it is found.</para>
+ <para>As mentioned above, a unit may be instantiated from a template file. This allows creation
+ of multiple units from a single configuration file. If systemd looks for a unit configuration
+ file, it will first search for the literal unit name in the file system. If that yields no
+ success and the unit 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
+ <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 for <filename>getty@.service</filename> and instantiate a service from that
+ configuration file if it is found.</para>
<para>To refer to the instance string from within the
configuration file you may use the special <literal>%i</literal>
@@ -289,40 +255,40 @@
</refsect1>
<refsect1>
- <title>Implicit Dependencies</title>
-
- <para>A number of unit dependencies are implicitly established,
- depending on unit type and unit configuration. These implicit
- dependencies can make unit configuration file cleaner. For the
- implicit dependencies in each unit type, please refer to
- section "Implicit Dependencies" in respective man pages.</para>
-
- <para>For example, service units with <varname>Type=dbus</varname>
- automatically acquire dependencies of type <varname>Requires=</varname>
- and <varname>After=</varname> on <filename>dbus.socket</filename>. See
- <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details.</para>
- </refsect1>
-
- <refsect1>
- <title>Default Dependencies</title>
-
- <para>Default dependencies are similar to implicit dependencies,
- but can be turned on and off by setting
- <varname>DefaultDependencies=</varname> to <varname>yes</varname>
- (the default) and <varname>no</varname>, while implicit dependencies
- are always in effect. See section "Default Dependencies" in respective
- man pages for the effect of enabling
- <varname>DefaultDependencies=</varname> in each unit types.</para>
-
- <para>For example, target units will complement all configured
- dependencies of type <varname>Wants=</varname> or
- <varname>Requires=</varname> with dependencies of type
- <varname>After=</varname> unless <varname>DefaultDependencies=no</varname>
- is set in the specified units. See
- <citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details. Note that this behavior can be turned off by setting
- <varname>DefaultDependencies=no</varname>.</para>
+ <title>Automatic dependencies</title>
+
+ <refsect2>
+ <title>Implicit Dependencies</title>
+
+ <para>A number of unit dependencies are implicitly established, depending on unit type and
+ unit configuration. These implicit dependencies can make unit configuration file cleaner. For
+ the implicit dependencies in each unit type, please refer to section "Implicit Dependencies"
+ in respective man pages.</para>
+
+ <para>For example, service units with <varname>Type=dbus</varname> automatically acquire
+ dependencies of type <varname>Requires=</varname> and <varname>After=</varname> on
+ <filename>dbus.socket</filename>. See
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details.</para>
+ </refsect2>
+
+ <refsect2>
+ <title>Default Dependencies</title>
+
+ <para>Default dependencies are similar to implicit dependencies, but can be turned on and off
+ by setting <varname>DefaultDependencies=</varname> to <varname>yes</varname> (the default) and
+ <varname>no</varname>, while implicit dependencies are always in effect. See section "Default
+ Dependencies" in respective man pages for the effect of enabling
+ <varname>DefaultDependencies=</varname> in each unit types.</para>
+
+ <para>For example, target units will complement all configured dependencies of type
+ <varname>Wants=</varname> or <varname>Requires=</varname> with dependencies of type
+ <varname>After=</varname> unless <varname>DefaultDependencies=no</varname> is set in the
+ specified units. See
+ <citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details. Note that this behavior can be turned off by setting
+ <varname>DefaultDependencies=no</varname>.</para>
+ </refsect2>
</refsect1>
<refsect1>
@@ -479,7 +445,7 @@
<para>The set of load paths for the user manager instance may be augmented or
changed using various environment variables. And environment variables may in
turn be set using environment generators, see
- <citerefentry><refentrytitle>system.environment-generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>systemd.environment-generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
In particular, <varname>$XDG_DATA_HOME</varname> and
<varname>$XDG_DATA_DIRS</varname> may be easily set using
<citerefentry><refentrytitle>systemd-environment-d-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
@@ -611,10 +577,12 @@
<varlistentry>
<term><varname>Requisite=</varname></term>
- <listitem><para>Similar to <varname>Requires=</varname>.
- However, if the units listed here are not started already,
- they will not be started and the transaction will fail
- immediately.</para>
+ <listitem><para>Similar to <varname>Requires=</varname>. However, if the units listed here
+ are not started already, they will not be started and the starting of this unit will fail
+ immediately. <varname>Requisite=</varname> does not imply an ordering dependency, even if
+ both units are started in the same transaction. Hence this setting should usually be
+ combined with <varname>After=</varname>, to ensure this unit is not started before the other
+ unit.</para>
<para>When <varname>Requisite=b.service</varname> is used on
<filename>a.service</filename>, this dependency will show as
@@ -954,7 +922,7 @@
activation may either never fail, or may succeed only a single time.</para>
<para>When a unit is unloaded due to the garbage collection logic (see above) its rate limit counters are
- flushed out too. This means that configuring start rate limiting for a unit that is not referenced continously
+ flushed out too. This means that configuring start rate limiting for a unit that is not referenced continuously
has no effect.</para></listitem>
</varlistentry>
@@ -1139,15 +1107,13 @@
kernels into older versions provided by distributions. Hence, this check is inherently unportable and should
not be used for units which may be used on different distributions.</para>
- <para><varname>ConditionSecurity=</varname> may be used to
- check whether the given security module is enabled on the
+ <para><varname>ConditionSecurity=</varname> may be used to check
+ whether the given security technology is enabled on the
system. Currently, the recognized values are
- <varname>selinux</varname>,
- <varname>apparmor</varname>,
- <varname>tomoyo</varname>,
- <varname>ima</varname>,
- <varname>smack</varname> and
- <varname>audit</varname>. The test may be negated by
+ <varname>selinux</varname>, <varname>apparmor</varname>,
+ <varname>tomoyo</varname>, <varname>ima</varname>,
+ <varname>smack</varname>, <varname>audit</varname> and
+ <varname>uefi-secureboot</varname>. The test may be negated by
prepending an exclamation mark.</para>
<para><varname>ConditionCapability=</varname> may be used to
@@ -1335,7 +1301,7 @@
<para>Unit settings that create a relationship with a second unit usually show up
in properties of both units, for example in <command>systemctl show</command>
output. In some cases the name of the property is the same as the name of the
- configuration setting, but not always. This table lists the pairs of properties
+ configuration setting, but not always. This table lists the properties
that are shown on two units which are connected through some dependency, and shows
which property on "source" unit corresponds to which property on the "target" unit.
</para>
@@ -1410,6 +1376,11 @@
<entry><varname>ReloadPropagatedFrom=</varname></entry>
<entry><varname>PropagatesReloadTo=</varname></entry>
</row>
+ <row>
+ <entry><varname>Following=</varname></entry>
+ <entry>n/a</entry>
+ <entry>An automatic property</entry>
+ </row>
</tbody>
</tgroup>
</table>
@@ -1425,7 +1396,7 @@
<para>Note: <varname>Triggers=</varname> is created implicitly between a socket,
path unit, or an automount unit, and the unit they activate. By default a unit
- with the same name is triggered, but this can be overriden using
+ with the same name is triggered, but this can be overridden using
<varname>Sockets=</varname>, <varname>Service=</varname>, and <varname>Unit=</varname>
settings. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
@@ -1435,6 +1406,10 @@
<citerefentry><refentrytitle>systemd.automount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. <varname>TriggersBy=</varname> is created implicitly on the
triggered unit.</para>
+
+ <para>Note: <varname>Following=</varname> is used to group device aliases and points to the
+ "primary" device unit that systemd is using to track device state, usually corresponding to a
+ sysfs path. It does not show up in the "target" unit.</para>
</refsect1>
<refsect1>
@@ -1520,7 +1495,7 @@
</variablelist>
<para>The following specifiers are interpreted in the Install
- section: %n, %N, %p, %i, %U, %u, %m, %H, %b, %v. For their meaning
+ section: %n, %N, %p, %i, %j, %U, %u, %m, %H, %b, %v. For their meaning
see the next section.
</para>
</refsect1>
@@ -1549,24 +1524,34 @@
</thead>
<tbody>
<row>
- <entry><literal>%n</literal></entry>
- <entry>Full unit name</entry>
- <entry></entry>
+ <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>%N</literal></entry>
- <entry>Full unit name</entry>
- <entry>Same as <literal>%n</literal>, but with the type suffix removed.</entry>
+ <entry><literal>%C</literal></entry>
+ <entry>Cache directory root</entry>
+ <entry>This is either <filename>/var/cache</filename> (for the system manager) or the path <literal>$XDG_CACHE_HOME</literal> resolves to (for user managers).</entry>
</row>
<row>
- <entry><literal>%p</literal></entry>
- <entry>Prefix name</entry>
- <entry>For instantiated units, this refers to the string before the first <literal>@</literal> character of the unit name. For non-instantiated units, same as <literal>%N</literal>.</entry>
+ <entry><literal>%E</literal></entry>
+ <entry>Configuration directory root</entry>
+ <entry>This is either <filename>/etc</filename> (for the system manager) or the path <literal>$XDG_CONFIG_HOME</literal> resolves to (for user managers).</entry>
</row>
<row>
- <entry><literal>%P</literal></entry>
- <entry>Unescaped prefix name</entry>
- <entry>Same as <literal>%p</literal>, but with escaping undone.</entry>
+ <entry><literal>%f</literal></entry>
+ <entry>Unescaped filename</entry>
+ <entry>This is either the unescaped instance name (if applicable) with <filename>/</filename> prepended (if applicable), or the unescaped prefix name prepended with <filename>/</filename>. This implements unescaping according to the rules for escaping absolute file system paths discussed above.</entry>
+ </row>
+ <row>
+ <entry><literal>%h</literal></entry>
+ <entry>User home directory</entry>
+ <entry>This is the home directory of the user running the service manager instance. In case of the system manager this resolves to <literal>/root</literal>.</entry>
+ </row>
+ <row>
+ <entry><literal>%H</literal></entry>
+ <entry>Host name</entry>
+ <entry>The hostname of the running system at the point in time the unit configuration is loaded.</entry>
</row>
<row>
<entry><literal>%i</literal></entry>
@@ -1579,44 +1564,44 @@
<entry>Same as <literal>%i</literal>, but with escaping undone.</entry>
</row>
<row>
- <entry><literal>%f</literal></entry>
- <entry>Unescaped filename</entry>
- <entry>This is either the unescaped instance name (if applicable) with <filename>/</filename> prepended (if applicable), or the unescaped prefix name prepended with <filename>/</filename>. This implements unescaping according to the rules for escaping absolute file system paths discussed above.</entry>
+ <entry><literal>%j</literal></entry>
+ <entry>Final component of the prefix</entry>
+ <entry>This is the string between the last <literal>-</literal> and the end of the prefix name. If there is no <literal>-</literal>, this is the same as <literal>%p</literal>.</entry>
</row>
<row>
- <entry><literal>%t</literal></entry>
- <entry>Runtime directory root</entry>
- <entry>This is either <filename>/run</filename> (for the system manager) or the path <literal>$XDG_RUNTIME_DIR</literal> resolves to (for user managers).</entry>
+ <entry><literal>%J</literal></entry>
+ <entry>Unescaped final component of the prefix</entry>
+ <entry>Same as <literal>%j</literal>, but with escaping undone.</entry>
</row>
<row>
- <entry><literal>%S</literal></entry>
- <entry>State directory root</entry>
- <entry>This is either <filename>/var/lib</filename> (for the system manager) or the path <literal>$XDG_CONFIG_HOME</literal> resolves to (for user managers).</entry>
+ <entry><literal>%L</literal></entry>
+ <entry>Log directory root</entry>
+ <entry>This is either <filename>/var/log</filename> (for the system manager) or the path <literal>$XDG_CONFIG_HOME</literal> resolves to with <filename noindex='true'>/log</filename> appended (for user managers).</entry>
</row>
<row>
- <entry><literal>%C</literal></entry>
- <entry>Cache directory root</entry>
- <entry>This is either <filename>/var/cache</filename> (for the system manager) or the path <literal>$XDG_CACHE_HOME</literal> resolves to (for user managers).</entry>
+ <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>%L</literal></entry>
- <entry>Log directory root</entry>
- <entry>This is either <filename>/var/log</filename> (for the system manager) or the path <literal>$XDG_CONFIG_HOME</literal> resolves to with <filename noindex='true'>/log</filename> appended (for user managers).</entry>
+ <entry><literal>%n</literal></entry>
+ <entry>Full unit name</entry>
+ <entry></entry>
</row>
<row>
- <entry><literal>%u</literal></entry>
- <entry>User name</entry>
- <entry>This is the name of the user running the service manager instance. In case of the system manager this resolves to <literal>root</literal>.</entry>
+ <entry><literal>%N</literal></entry>
+ <entry>Full unit name</entry>
+ <entry>Same as <literal>%n</literal>, but with the type suffix removed.</entry>
</row>
<row>
- <entry><literal>%U</literal></entry>
- <entry>User UID</entry>
- <entry>This is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to <literal>0</literal>.</entry>
+ <entry><literal>%p</literal></entry>
+ <entry>Prefix name</entry>
+ <entry>For instantiated units, this refers to the string before the first <literal>@</literal> character of the unit name. For non-instantiated units, same as <literal>%N</literal>.</entry>
</row>
<row>
- <entry><literal>%h</literal></entry>
- <entry>User home directory</entry>
- <entry>This is the home directory of the user running the service manager instance. In case of the system manager this resolves to <literal>/root</literal>.</entry>
+ <entry><literal>%P</literal></entry>
+ <entry>Unescaped prefix name</entry>
+ <entry>Same as <literal>%p</literal>, but with escaping undone.</entry>
</row>
<row>
<entry><literal>%s</literal></entry>
@@ -1624,19 +1609,29 @@
<entry>This is the shell of the user running the service manager instance. In case of the system manager this resolves to <literal>/bin/sh</literal>.</entry>
</row>
<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>
+ <entry><literal>%S</literal></entry>
+ <entry>State directory root</entry>
+ <entry>This is either <filename>/var/lib</filename> (for the system manager) or the path <literal>$XDG_CONFIG_HOME</literal> resolves to (for user managers).</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>
+ <entry><literal>%t</literal></entry>
+ <entry>Runtime directory root</entry>
+ <entry>This is either <filename>/run</filename> (for the system manager) or the path <literal>$XDG_RUNTIME_DIR</literal> resolves to (for user managers).</entry>
</row>
<row>
- <entry><literal>%H</literal></entry>
- <entry>Host name</entry>
- <entry>The hostname of the running system at the point in time the unit configuration is loaded.</entry>
+ <entry><literal>%T</literal></entry>
+ <entry>Directory for temporary files</entry>
+ <entry>This is either <filename>/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
+ </row>
+ <row>
+ <entry><literal>%u</literal></entry>
+ <entry>User name</entry>
+ <entry>This is the name of the user running the service manager instance. In case of the system manager this resolves to <literal>root</literal>.</entry>
+ </row>
+ <row>
+ <entry><literal>%U</literal></entry>
+ <entry>User UID</entry>
+ <entry>This is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to <literal>0</literal>.</entry>
</row>
<row>
<entry><literal>%v</literal></entry>
@@ -1644,6 +1639,11 @@
<entry>Identical to <command>uname -r</command> output</entry>
</row>
<row>
+ <entry><literal>%V</literal></entry>
+ <entry>Directory for larger and persistent temporary files</entry>
+ <entry>This is either <filename>/var/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
+ </row>
+ <row>
<entry><literal>%%</literal></entry>
<entry>Single percent sign</entry>
<entry>Use <literal>%%</literal> in place of <literal>%</literal> to specify a single percent sign.</entry>
diff --git a/man/systemd.xml b/man/systemd.xml
index 26555036c4..89086558c7 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="systemd"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>systemd</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -110,6 +84,13 @@
understood in unit definition files.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>--dump-bus-properties</option></term>
+
+ <listitem><para>Dump exposed bus properties. This outputs
+ a terse but complete list of properties exposed to dbus.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>--unit=</option></term>
<listitem><para>Set default unit to activate on startup. If
@@ -755,15 +736,18 @@
<varlistentry>
<term><constant>SIGRTMIN+22</constant></term>
+
+ <listitem><para>Sets the service manager's log level to <literal>debug</literal>, in a fashion equivalent to
+ <varname>systemd.log_level=debug</varname> on the kernel command line.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><constant>SIGRTMIN+23</constant></term>
- <listitem><para>Sets the log level to <literal>debug</literal>
- (or <literal>info</literal> on
- <constant>SIGRTMIN+23</constant>), as controlled via
- <varname>systemd.log_level=debug</varname> (or
- <varname>systemd.log_level=info</varname> on
- <constant>SIGRTMIN+23</constant>) on the kernel command
- line.</para></listitem>
+ <listitem><para>Restores the log level to its configured value. The configured value is derived from – in order
+ of priority – the value specified with <varname>systemd.log-level=</varname> on the kernel command line, or the
+ value specified with <option>LogLevel=</option> in the configuration file, or the built-in default of
+ <literal>info</literal>.</para></listitem>
</varlistentry>
<varlistentry>
@@ -775,20 +759,21 @@
<varlistentry>
<term><constant>SIGRTMIN+26</constant></term>
+
+ <listitem><para>Restores the log target to its configured value. The configured value is derived from – in
+ order of priority – the value specified with <varname>systemd.log-target=</varname> on the kernel command line,
+ or the value specified with <option>LogTarget=</option> in the configuration file, or the built-in
+ default.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><constant>SIGRTMIN+27</constant></term>
<term><constant>SIGRTMIN+28</constant></term>
- <listitem><para>Sets the log target to
- <literal>journal-or-kmsg</literal> (or
- <literal>console</literal> on
- <constant>SIGRTMIN+27</constant>, <literal>kmsg</literal> on
- <constant>SIGRTMIN+28</constant>), as controlled via
- <varname>systemd.log_target=journal-or-kmsg</varname> (or
- <varname>systemd.log_target=console</varname> on
- <constant>SIGRTMIN+27</constant> or
- <varname>systemd.log_target=kmsg</varname> on
- <constant>SIGRTMIN+28</constant>) on the kernel command
- line.</para></listitem>
+ <listitem><para>Sets the log target to <literal>console</literal> on <constant>SIGRTMIN+27</constant> (or
+ <literal>kmsg</literal> on <constant>SIGRTMIN+28</constant>), in a fashion equivalent to
+ <varname>systemd.log_target=console</varname> (or <varname>systemd.log_target=kmsg</varname> on
+ <constant>SIGRTMIN+28</constant>) on the kernel command line.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
@@ -869,6 +854,15 @@
</varlistentry>
<varlistentry>
+ <term><varname>$SYSTEMD_URLIFY</varname></term>
+
+ <listitem><para>The value must be a boolean. Controls whether clickable links should be generated in the output
+ for terminal emulators supporting this. This can be specified to override the decision that
+ <command>systemd</command> makes based on <varname>$TERM</varname> and other conditions.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>$LISTEN_PID</varname></term>
<term><varname>$LISTEN_FDS</varname></term>
<term><varname>$LISTEN_FDNAMES</varname></term>
diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml
index 1c87b1bdd1..e47d36c73a 100644
--- a/man/sysusers.d.xml
+++ b/man/sysusers.d.xml
@@ -3,23 +3,6 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="sysusers.d" conditional='ENABLE_SYSUSERS'
xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -27,15 +10,6 @@
<refentryinfo>
<title>sysusers.d</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -243,6 +217,66 @@ u root 0 "Superuser" /root /bin/zsh</pro
</refsect1>
<refsect1>
+ <title>Specifiers</title>
+
+ <para>Specifiers can be used in the "Name", "ID", "GECOS", "Home directory", and "Shell" fields.
+ An unknown or unresolvable specifier is treated as invalid configuration.
+ 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>%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>%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>%T</literal></entry>
+ <entry>Directory for temporary files</entry>
+ <entry>This is either <filename>/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</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>%V</literal></entry>
+ <entry>Directory for larger and persistent temporary files</entry>
+ <entry>This is either <filename>/var/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
+ </row>
+ <row>
+ <entry><literal>%%</literal></entry>
+ <entry>Escaped <literal>%</literal></entry>
+ <entry>Single percent sign.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </refsect1>
+
+ <refsect1>
<title>Idempotence</title>
<para>Note that <command>systemd-sysusers</command> will do nothing if the
diff --git a/man/telinit.xml b/man/telinit.xml
index 70044cc1da..5a48caff2b 100644
--- a/man/telinit.xml
+++ b/man/telinit.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="telinit"
@@ -29,15 +12,6 @@
<refentryinfo>
<title>telinit</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/timedatectl.xml b/man/timedatectl.xml
index f24ec2d4c8..39cd78666e 100644
--- a/man/timedatectl.xml
+++ b/man/timedatectl.xml
@@ -4,40 +4,14 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- 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/>.
-->
-<refentry id="timedatectl" conditional='ENABLE_TIMEDATED'
+<refentry id="timedatectl" conditional='ENABLE_TIMEDATECTL'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>timedatectl</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -66,6 +40,11 @@
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to initialize the system time zone for mounted (but not booted)
system images.</para>
+
+ <para><command>timedatectl</command> may be used to show the current status of
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ </para>
+
</refsect1>
<refsect1>
@@ -91,6 +70,43 @@
clock.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--monitor</option></term>
+
+ <listitem><para>If <command>timesync-status</command> is invoked and this option is passed,
+ then <command>timedatectl</command> monitors the status of
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ and updates the outputs. Use Ctrl-C to terminate the monitoring.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-a</option></term>
+ <term><option>-all</option></term>
+
+ <listitem><para>When showing properties of
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ show all properties regardless of whether they are set or not.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-p</option></term>
+ <term><option>--property=</option></term>
+
+ <listitem><para>When showing properties of
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ limit display to certain properties as specified as argument. If not specified, all set properties are shown.
+ The argument should be a property name, such as <literal>ServerName</literal>. If specified more than once,
+ all properties with the specified names are shown.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--value</option></term>
+
+ <listitem>
+ <para>When printing properties with <command>show-timesync</command>, only print the value, and skip the
+ property name and <literal>=</literal>.</para></listitem>
+ </varlistentry>
+
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="user-system-options.xml" xpointer="machine" />
@@ -118,6 +134,16 @@
</varlistentry>
<varlistentry>
+ <term><command>show</command></term>
+
+ <listitem><para>Show the same information as <option>status</option>, but in machine readable form.
+ This command is intended to be used whenever computer-parsable output is required.
+ Use <option>status</option> if you are looking for formatted human-readable output.</para>
+ <para>By default, empty properties are suppressed. Use <option>--all</option> to show those too.
+ To select specific properties to show, use <option>--property=</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><command>set-time [TIME]</command></term>
<listitem><para>Set the system clock to the specified time.
@@ -169,32 +195,44 @@
<varlistentry>
<term><command>set-ntp [BOOL]</command></term>
- <listitem><para>Takes a boolean argument. Controls whether
- network time synchronization is active and enabled (if
- available). This enables and starts, or disables and stops the
- <filename>systemd-timesyncd.service</filename> unit. It does
- not affect the state of any other, unrelated network time
- synchronization services that might be installed on the
- system. This command is hence mostly equivalent to:
- <command>systemctl enable --now
- systemd-timesyncd.service</command> and <command>systemctl
- disable --now systemd-timesyncd.service</command>, but is
- protected by a different access policy.</para>
-
- <para>Note that even if time synchronization is turned off
- with this command, another unrelated system service might
- still synchronize the clock with the network. Also note that,
- strictly speaking,
- <filename>systemd-timesyncd.service</filename> does more than
- just network time synchronization, as it ensures a monotonic
- clock on systems without RTC even if no network is
- available. See
- <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for details about this.</para></listitem>
+ <listitem><para>Takes a boolean argument. Controls whether network time synchronization is active
+ and enabled (if available). If the argument is true, this enables and starts the first existed
+ service listed in the environment variable <varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname>
+ of <filename>systemd-timedated.service</filename>. If the argument is false, then this disables and
+ stops the all services listed in <varname>$SYSTEMD_TIMEDATED_NTP_SERVICES</varname>.</para></listitem>
</varlistentry>
</variablelist>
+ <refsect2>
+ <title>systemd-timesyncd Commands</title>
+
+ <para>The following commands are specific to
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>timesync-status</command></term>
+
+ <listitem><para>Show current status of
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ If <option>--monitor</option> is specified, then this will monitor the status updates.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>show-timesync</command></term>
+
+ <listitem><para>Show the same information as <option>timesync-status</option>, but in machine readable form.
+ This command is intended to be used whenever computer-parsable output is required.
+ Use <option>timesync-status</option> if you are looking for formatted human-readable output.</para>
+ <para>By default, empty properties are suppressed. Use <option>--all</option> to show those too.
+ To select specific properties to show, use <option>--property=</option>.</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect2>
+
</refsect1>
<refsect1>
@@ -210,13 +248,13 @@
<title>Examples</title>
<para>Show current settings:
<programlisting>$ timedatectl
- Local time: Thu 2017-09-21 16:08:56 CEST
- Universal time: Thu 2017-09-21 14:08:56 UTC
- RTC time: Thu 2017-09-21 14:08:56
- Time zone: Europe/Warsaw (CEST, +0200)
- System clock synchronized: yes
-systemd-timesyncd.service active: yes
- RTC in local TZ: no</programlisting>
+ Local time: Thu 2017-09-21 16:08:56 CEST
+ Universal time: Thu 2017-09-21 14:08:56 UTC
+ RTC time: Thu 2017-09-21 14:08:56
+ Time zone: Europe/Warsaw (CEST, +0200)
+System clock synchronized: yes
+ NTP service: active
+ RTC in local TZ: no</programlisting>
</para>
<para>Enable network time synchronization:
@@ -238,6 +276,25 @@ Password: ********
└─595 /usr/lib/systemd/systemd-timesyncd
…</programlisting>
</para>
+
+ <para>Show current status of
+ <citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>:
+ <programlisting>$ timedatectl timesync-status
+ Server: 216.239.38.15 (time4.google.com)
+Poll interval: 1min 4s (min: 32s; max 34min 8s)
+ Leap: normal
+ Version: 4
+ Stratum: 1
+ Reference: GPS
+ Precision: 1us (-20)
+Root distance: 335us (max: 5s)
+ Offset: +316us
+ Delay: 349us
+ Jitter: 0
+ Packet count: 1
+ Frequency: -8.802ppm</programlisting>
+ </para>
+
</refsect1>
<refsect1>
diff --git a/man/timesyncd.conf.xml b/man/timesyncd.conf.xml
index 812b16e1b9..8ba639f3ae 100644
--- a/man/timesyncd.conf.xml
+++ b/man/timesyncd.conf.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="timesyncd.conf" conditional='ENABLE_TIMESYNCD'
@@ -28,15 +11,6 @@
<refentryinfo>
<title>timesyncd.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -60,9 +34,9 @@
<refsect1>
<title>Description</title>
- <para>These configuration files control NTP network time
- synchronization.</para>
-
+ <para>These configuration files control NTP network time synchronization. See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 7341495b1d..e2e2eac228 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -3,37 +3,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- This file is part of systemd.
-
- Copyright 2010 Brandon Philips
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 Brandon Philips
-->
<refentry id="tmpfiles.d">
<refentryinfo>
<title>tmpfiles.d</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Documentation</contrib>
- <firstname>Brandon</firstname>
- <surname>Philips</surname>
- <email>brandon@ifup.org</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -625,39 +601,39 @@ r! /tmp/.X[0-9]*-lock</programlisting>
</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>%C</literal></entry>
+ <entry>System or user cache directory</entry>
+ <entry>In <option>--user</option> mode, this is the same as <varname>$XDG_CACHE_HOME</varname>, and <filename>/var/cache</filename> otherwise.</entry>
+ </row>
+ <row>
+ <entry><literal>%h</literal></entry>
+ <entry>User home directory</entry>
+ <entry>This is the home directory of the user running the command. In case of the system instance this resolves to <literal>/root</literal>.</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>%U</literal></entry>
- <entry>User UID</entry>
- <entry>This is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to <constant>0</constant>.</entry>
+ <entry><literal>%L</literal></entry>
+ <entry>System or user log directory</entry>
+ <entry>In <option>--user</option> mode, this is the same as <varname>$XDG_CONFIG_HOME</varname> with <filename noindex='true'>/log</filename> appended, and <filename>/var/log</filename> otherwise.</entry>
</row>
<row>
- <entry><literal>%u</literal></entry>
- <entry>User name</entry>
- <entry>This is the name of the user running the service manager instance. In case of the system manager this resolves to <literal>root</literal>.</entry>
+ <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>%h</literal></entry>
- <entry>User home directory</entry>
- <entry>This is the home directory of the user running the service manager instance. In case of the system manager this resolves to <literal>/root</literal>.</entry>
+ <entry><literal>%S</literal></entry>
+ <entry>System or user state directory</entry>
+ <entry>In <option>--user</option> mode, this is the same as <varname>$XDG_CONFIG_HOME</varname>, and <filename>/var/lib</filename> otherwise.</entry>
</row>
<row>
<entry><literal>%t</literal></entry>
@@ -665,19 +641,29 @@ r! /tmp/.X[0-9]*-lock</programlisting>
<entry>In --user mode, this is the same <varname>$XDG_RUNTIME_DIR</varname>, and <filename>/run</filename> otherwise.</entry>
</row>
<row>
- <entry><literal>%S</literal></entry>
- <entry>System or user state directory</entry>
- <entry>In <option>--user</option> mode, this is the same as <varname>$XDG_CONFIG_HOME</varname>, and <filename>/var/lib</filename> otherwise.</entry>
+ <entry><literal>%T</literal></entry>
+ <entry>Directory for temporary files</entry>
+ <entry>This is either <filename>/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
</row>
<row>
- <entry><literal>%C</literal></entry>
- <entry>System or user cache directory</entry>
- <entry>In <option>--user</option> mode, this is the same as <varname>$XDG_CACHE_HOME</varname>, and <filename>/var/cache</filename> otherwise.</entry>
+ <entry><literal>%u</literal></entry>
+ <entry>User name</entry>
+ <entry>This is the name of the user running the command. In case of the system instance this resolves to <literal>root</literal>.</entry>
</row>
<row>
- <entry><literal>%L</literal></entry>
- <entry>System or user log directory</entry>
- <entry>In <option>--user</option> mode, this is the same as <varname>$XDG_CONFIG_HOME</varname> with <filename noindex='true'>/log</filename> appended, and <filename>/var/log</filename> otherwise.</entry>
+ <entry><literal>%U</literal></entry>
+ <entry>User UID</entry>
+ <entry>This is the numeric UID of the user running the command. In case of the system instance this resolves to <constant>0</constant>.</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>%V</literal></entry>
+ <entry>Directory for larger and persistent temporary files</entry>
+ <entry>This is either <filename>/var/tmp</filename> or the path <literal>$TMPDIR</literal>, <literal>$TEMP</literal> or <literal>$TMP</literal> are set to.</entry>
</row>
<row>
<entry><literal>%%</literal></entry>
diff --git a/man/udev.conf.xml b/man/udev.conf.xml
index 2339e8b9d3..29c9743d1d 100644
--- a/man/udev.conf.xml
+++ b/man/udev.conf.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="udev.conf"
@@ -29,14 +12,6 @@
<refentryinfo>
<title>udev.conf</title>
<productname>systemd</productname>
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev.xml b/man/udev.xml
index 8e58ead0ba..15e6d8eae1 100644
--- a/man/udev.xml
+++ b/man/udev.xml
@@ -4,44 +4,13 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers
- Copyright 2014 Jason St. John
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Jason St. John
-->
<refentry id="udev">
<refentryinfo>
<title>udev</title>
<productname>systemd</productname>
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Greg</firstname>
- <surname>Kroah-Hartmann</surname>
- <email>greg@kroah.com</email>
- </author>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_device_get_syspath.xml b/man/udev_device_get_syspath.xml
index 1eb029f8f9..d4dc79983f 100644
--- a/man/udev_device_get_syspath.xml
+++ b/man/udev_device_get_syspath.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_device_get_syspath"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_device_get_syspath</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_device_has_tag.xml b/man/udev_device_has_tag.xml
index cdfcd7b727..f34ae9ed37 100644
--- a/man/udev_device_has_tag.xml
+++ b/man/udev_device_has_tag.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_device_has_tag"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_device_has_tag</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_device_new_from_syspath.xml b/man/udev_device_new_from_syspath.xml
index 13f1b4ccef..8e207b4aab 100644
--- a/man/udev_device_new_from_syspath.xml
+++ b/man/udev_device_new_from_syspath.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_device_new_from_syspath"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_device_new_from_syspath</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_enumerate_add_match_subsystem.xml b/man/udev_enumerate_add_match_subsystem.xml
index fee861c65d..a45ca5d2d2 100644
--- a/man/udev_enumerate_add_match_subsystem.xml
+++ b/man/udev_enumerate_add_match_subsystem.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_enumerate_add_match_subsystem"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_enumerate_add_match_subsystem</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_enumerate_new.xml b/man/udev_enumerate_new.xml
index e195ad5105..3ece35eab0 100644
--- a/man/udev_enumerate_new.xml
+++ b/man/udev_enumerate_new.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_enumerate_new"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_enumerate_new</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_enumerate_scan_devices.xml b/man/udev_enumerate_scan_devices.xml
index 3abfcef84e..770ddb946d 100644
--- a/man/udev_enumerate_scan_devices.xml
+++ b/man/udev_enumerate_scan_devices.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_enumerate_scan_devices"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_enumerate_scan_devices</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_list_entry.xml b/man/udev_list_entry.xml
index 12b48357ff..0b1d28a0ee 100644
--- a/man/udev_list_entry.xml
+++ b/man/udev_list_entry.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_list_entry"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_list_entry</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_monitor_filter_update.xml b/man/udev_monitor_filter_update.xml
index 3590a3ccd6..f5e4d075c8 100644
--- a/man/udev_monitor_filter_update.xml
+++ b/man/udev_monitor_filter_update.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_monitor_filter_update"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_monitor_filter_update</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_monitor_new_from_netlink.xml b/man/udev_monitor_new_from_netlink.xml
index 90ce121611..47fa5ab49b 100644
--- a/man/udev_monitor_new_from_netlink.xml
+++ b/man/udev_monitor_new_from_netlink.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_monitor_new_from_netlink"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_monitor_new_from_netlink</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_monitor_receive_device.xml b/man/udev_monitor_receive_device.xml
index abc9615eb5..6a4aae90f7 100644
--- a/man/udev_monitor_receive_device.xml
+++ b/man/udev_monitor_receive_device.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_monitor_receive_device"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_monitor_receive_device</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udev_new.xml b/man/udev_new.xml
index b4520d7e36..3971acbc70 100644
--- a/man/udev_new.xml
+++ b/man/udev_new.xml
@@ -7,23 +7,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.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/>.
-->
<refentry id="udev_new"
@@ -32,15 +15,6 @@
<refentryinfo>
<title>udev_new</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>David</firstname>
- <surname>Herrmann</surname>
- <email>dh.herrmann@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/udevadm.xml b/man/udevadm.xml
index 6bb54c86d8..f292be4887 100644
--- a/man/udevadm.xml
+++ b/man/udevadm.xml
@@ -4,23 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010-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/>.
-->
<refentry id="udevadm"
@@ -29,14 +12,6 @@
<refentryinfo>
<title>udevadm</title>
<productname>systemd</productname>
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -91,11 +66,11 @@
<term><option>-d</option></term>
<term><option>--debug</option></term>
<listitem>
- <para>Print debug messages to standard error.</para>
+ <para>Print debug messages to standard error. This option is implied in <command>udevadm test</command> and
+ <command>udevadm test-builtin</command> commands.</para>
</listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
@@ -202,7 +177,6 @@
</listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
@@ -312,11 +286,11 @@
<term><option>-y</option></term>
<term><option>--sysname-match=<replaceable>PATH</replaceable></option></term>
<listitem>
- <para>Trigger events for devices for which the last component
- (i.e. the filename) of the <filename>/sys</filename> path matches
- the specified <replaceable>PATH</replaceable>. This option can be
- specified multiple times and also supports shell style pattern
- matching.</para>
+ <para>Trigger events for devices for which the last component
+ (i.e. the filename) of the <filename>/sys</filename> path matches
+ the specified <replaceable>PATH</replaceable>. This option can be
+ specified multiple times and also supports shell style pattern
+ matching.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -347,7 +321,6 @@
</listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
@@ -380,7 +353,6 @@
</listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
</refsect2>
@@ -456,7 +428,6 @@
</listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
</refsect2>
@@ -505,7 +476,6 @@
</listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
</refsect2>
@@ -537,7 +507,6 @@
</listitem>
</varlistentry>
- <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
</refsect2>
@@ -551,7 +520,6 @@
for device <replaceable>DEVPATH</replaceable>, and print debug
output.</para>
<variablelist>
- <xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
</refsect2>
diff --git a/man/user-system-options.xml b/man/user-system-options.xml
index d6a5eeffb7..eb875661de 100644
--- a/man/user-system-options.xml
+++ b/man/user-system-options.xml
@@ -4,24 +4,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<variablelist>
diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml
index fecbfd82bc..fc8b2cb3ef 100644
--- a/man/vconsole.conf.xml
+++ b/man/vconsole.conf.xml
@@ -4,38 +4,12 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="vconsole.conf" conditional='ENABLE_VCONSOLE'>
<refentryinfo>
<title>vconsole.conf</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/meson.build b/meson.build
index a2dc4040df..04331dd41a 100644
--- a/meson.build
+++ b/meson.build
@@ -1,22 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
project('systemd', 'c',
- version : '238',
+ version : '239',
license : 'LGPLv2+',
default_options: [
'c_std=gnu99',
@@ -24,13 +9,13 @@ project('systemd', 'c',
'sysconfdir=/etc',
'localstatedir=/var',
],
- meson_version : '>= 0.41',
+ meson_version : '>= 0.44',
)
-libsystemd_version = '0.22.0'
-libudev_version = '1.6.10'
+libsystemd_version = '0.23.0'
+libudev_version = '1.6.11'
-# We need the same data in three different formats, ugh!
+# We need the same data in two different formats, ugh!
# Also, for hysterical reasons, we use different variable
# names, sometimes. Not all variables are included in every
# set. Ugh, ugh, ugh!
@@ -42,8 +27,6 @@ substs = configuration_data()
substs.set('PACKAGE_URL', 'https://www.freedesktop.org/wiki/Software/systemd')
substs.set('PACKAGE_VERSION', meson.project_version())
-m4_defines = []
-
#####################################################################
# Try to install the git pre-commit hook
@@ -80,10 +63,8 @@ endif
sysvinit_path = get_option('sysvinit-path')
sysvrcnd_path = get_option('sysvrcnd-path')
-have = sysvinit_path != '' and sysvrcnd_path != ''
-conf.set10('HAVE_SYSV_COMPAT', have,
+conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '',
description : 'SysV init scripts and rcN.d links are supported')
-m4_defines += have ? ['-DHAVE_SYSV_COMPAT'] : []
# join_paths ignore the preceding arguments if an absolute component is
# encountered, so this should canonicalize various paths when they are
@@ -155,6 +136,7 @@ testsdir = join_paths(prefixdir, 'lib/systemd/tests')
systemdstatedir = join_paths(localstatedir, 'lib/systemd')
catalogstatedir = join_paths(systemdstatedir, 'catalog')
randomseeddir = join_paths(localstatedir, 'lib/systemd')
+profiledir = join_paths(rootlibexecdir, 'portable', 'profile')
docdir = get_option('docdir')
if docdir == ''
@@ -237,7 +219,7 @@ conf.set_quoted('VENDOR_KEYRING_PATH', join_paths(rootlib
conf.set_quoted('USER_KEYRING_PATH', join_paths(pkgsysconfdir, 'import-pubring.gpg'))
conf.set_quoted('DOCUMENT_ROOT', join_paths(pkgdatadir, 'gatewayd'))
conf.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'true' : 'false')
-conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_ON_OFF', memory_accounting_default ? 'on' : 'off')
+conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_YES_NO', memory_accounting_default ? 'yes' : 'no')
conf.set_quoted('ABS_BUILD_DIR', meson.build_root())
conf.set_quoted('ABS_SRC_DIR', meson.source_root())
@@ -258,12 +240,14 @@ substs.set('userpresetdir', userpresetdir)
substs.set('udevhwdbdir', udevhwdbdir)
substs.set('udevrulesdir', udevrulesdir)
substs.set('udevlibexecdir', udevlibexecdir)
+substs.set('environmentdir', environmentdir)
substs.set('catalogdir', catalogdir)
substs.set('tmpfilesdir', tmpfilesdir)
substs.set('sysusersdir', sysusersdir)
substs.set('sysctldir', sysctldir)
substs.set('binfmtdir', binfmtdir)
substs.set('modulesloaddir', modulesloaddir)
+substs.set('modprobedir', modprobedir)
substs.set('systemgeneratordir', systemgeneratordir)
substs.set('usergeneratordir', usergeneratordir)
substs.set('systemenvgeneratordir', systemenvgeneratordir)
@@ -308,57 +292,79 @@ if want_ossfuzz
fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
endif
-foreach arg : ['-Wextra',
- '-Werror=undef',
- '-Wlogical-op',
- '-Wmissing-include-dirs',
- '-Wold-style-definition',
- '-Wpointer-arith',
- '-Winit-self',
- '-Wdeclaration-after-statement',
- '-Wfloat-equal',
- '-Wsuggest-attribute=noreturn',
- '-Werror=missing-prototypes',
- '-Werror=implicit-function-declaration',
- '-Werror=missing-declarations',
- '-Werror=return-type',
- '-Werror=incompatible-pointer-types',
- '-Werror=format=2',
- '-Wstrict-prototypes',
- '-Wredundant-decls',
- '-Wmissing-noreturn',
- '-Wimplicit-fallthrough=5',
- '-Wshadow',
- '-Wendif-labels',
- '-Wstrict-aliasing=2',
- '-Wwrite-strings',
- '-Werror=overflow',
- '-Wdate-time',
- '-Wnested-externs',
- '-ffast-math',
- '-fno-common',
- '-fdiagnostics-show-option',
- '-fno-strict-aliasing',
- '-fvisibility=hidden',
- '-fstack-protector',
- '-fstack-protector-strong',
- '--param=ssp-buffer-size=4',
- ]
- if cc.has_argument(arg)
- add_project_arguments(arg, language : 'c')
- endif
-endforeach
+possible_cc_flags = [
+ '-Wextra',
+ '-Werror=undef',
+ '-Wlogical-op',
+ '-Wmissing-include-dirs',
+ '-Wold-style-definition',
+ '-Wpointer-arith',
+ '-Winit-self',
+ '-Wfloat-equal',
+ '-Wsuggest-attribute=noreturn',
+ '-Werror=missing-prototypes',
+ '-Werror=implicit-function-declaration',
+ '-Werror=missing-declarations',
+ '-Werror=return-type',
+ '-Werror=incompatible-pointer-types',
+ '-Werror=format=2',
+ '-Wstrict-prototypes',
+ '-Wredundant-decls',
+ '-Wmissing-noreturn',
+ '-Wimplicit-fallthrough=5',
+ '-Wshadow',
+ '-Wendif-labels',
+ '-Wstrict-aliasing=2',
+ '-Wwrite-strings',
+ '-Werror=overflow',
+ '-Werror=shift-count-overflow',
+ '-Werror=shift-overflow=2',
+ '-Wdate-time',
+ '-Wnested-externs',
+ '-ffast-math',
+ '-fno-common',
+ '-fdiagnostics-show-option',
+ '-fno-strict-aliasing',
+ '-fvisibility=hidden',
+ '-fstack-protector',
+ '-fstack-protector-strong',
+ '--param=ssp-buffer-size=4',
+]
+
+# --as-needed and --no-undefined are provided by meson by default,
+# run mesonconf to see what is enabled
+possible_link_flags = [
+ '-Wl,-z,relro',
+ '-Wl,-z,now',
+]
# the oss-fuzz fuzzers are not built with -fPIE, so don't
# enable it when we are linking against them
if not fuzzer_build
- if cc.has_argument('-fPIE')
- add_project_arguments('-fPIE', language : 'c')
- endif
+ possible_cc_flags += '-fPIE'
+ possible_link_flags += '-pie'
+endif
+
+if cc.get_id() == 'clang'
+ possible_cc_flags += [
+ '-Wno-typedef-redefinition',
+ '-Wno-gnu-variable-sized-type-not-at-end',
+ ]
+endif
+
+if get_option('buildtype') != 'debug'
+ possible_cc_flags += [
+ '-ffunction-sections',
+ '-fdata-sections',
+ ]
+
+ possible_link_flags += '-Wl,--gc-sections'
endif
+add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c')
+
# "negative" arguments: gcc on purpose does not return an error for "-Wno-"
-# arguments, just emits a warnings. So test for the "positive" version instead.
+# arguments, just emits a warning. So test for the "positive" version instead.
foreach arg : ['unused-parameter',
'missing-field-initializers',
'unused-result',
@@ -383,67 +389,18 @@ if cc.compiles('''
add_project_arguments('-Werror=shadow', language : 'c')
endif
-if cc.get_id() == 'clang'
- foreach arg : ['-Wno-typedef-redefinition',
- '-Wno-gnu-variable-sized-type-not-at-end',
- ]
- if cc.has_argument(arg)
- add_project_arguments(arg, language : 'c')
- endif
- endforeach
-endif
-
link_test_c = files('tools/meson-link-test.c')
-# --as-needed and --no-undefined are provided by meson by default,
-# run mesonconf to see what is enabled
-foreach arg : ['-Wl,-z,relro',
- '-Wl,-z,now',
- '-pie',
- ]
-
+foreach arg : possible_link_flags
have = run_command(check_compilation_sh,
cc.cmd_array(), '-x', 'c', arg,
'-include', link_test_c).returncode() == 0
message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no'))
- if have and (arg != '-pie' or not fuzzer_build)
- add_project_link_arguments(arg, language : 'c')
- endif
-endforeach
-
-# Check if various sanitizers are supported
-sanitizers = []
-foreach arg : ['address']
-
- have = run_command(check_compilation_sh,
- cc.cmd_array(), '-x', 'c',
- '-fsanitize=@0@'.format(arg),
- '-include', link_test_c).returncode() == 0
- message('@0@ sanitizer supported: @1@'.format(arg, have ? 'yes' : 'no'))
if have
- sanitizers += arg
+ add_project_link_arguments(arg, language : 'c')
endif
endforeach
-if get_option('buildtype') != 'debug'
- foreach arg : ['-ffunction-sections',
- '-fdata-sections']
- if cc.has_argument(arg)
- add_project_arguments(arg, language : 'c')
- endif
- endforeach
-
- foreach arg : ['-Wl,--gc-sections']
- have = run_command(check_compilation_sh,
- cc.cmd_array(), '-x', 'c', arg,
- '-include', link_test_c).returncode() == 0
- message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no'))
- if have
- add_project_link_arguments(arg, language : 'c')
- endif
- endforeach
-endif
-
cpp = ' '.join(cc.cmd_array()) + ' -E'
#####################################################################
@@ -564,6 +521,7 @@ m4 = find_program('m4')
stat = find_program('stat')
git = find_program('git', required : false)
env = find_program('env')
+perl = find_program('perl', required : false)
meson_make_symlink = meson.source_root() + '/tools/meson-make-symlink.sh'
mkdir_p = 'mkdir -p $DESTDIR/@0@'
@@ -574,7 +532,6 @@ splash_bmp = files('test/splash.bmp')
# /usr/sbin, /sbin, and fall back to the default from middle column.
progs = [['quotaon', '/usr/sbin/quotaon' ],
['quotacheck', '/usr/sbin/quotacheck' ],
- ['kill', '/usr/bin/kill' ],
['kmod', '/usr/bin/kmod' ],
['kexec', '/usr/sbin/kexec' ],
['sulogin', '/usr/sbin/sulogin' ],
@@ -725,18 +682,18 @@ getent_result = run_command('getent', 'passwd', '65534')
if getent_result.returncode() == 0
name = getent_result.stdout().split(':')[0]
if name != nobody_user
- message('WARNING:\n' +
- ' The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) +
- ' Your build will result in an user table setup that is incompatible with the local system.')
+ warning('\n' +
+ 'The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) +
+ 'Your build will result in an user table setup that is incompatible with the local system.')
endif
endif
id_result = run_command('id', '-u', nobody_user)
if id_result.returncode() == 0
id = id_result.stdout().to_int()
if id != 65534
- message('WARNING:\n' +
- ' The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) +
- ' Your build will result in an user table setup that is incompatible with the local system.')
+ warning('\n' +
+ 'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) +
+ 'Your build will result in an user table setup that is incompatible with the local system.')
endif
endif
@@ -744,24 +701,24 @@ getent_result = run_command('getent', 'group', '65534')
if getent_result.returncode() == 0
name = getent_result.stdout().split(':')[0]
if name != nobody_group
- message('WARNING:\n' +
- ' The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) +
- ' Your build will result in an group table setup that is incompatible with the local system.')
+ warning('\n' +
+ 'The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) +
+ 'Your build will result in an group table setup that is incompatible with the local system.')
endif
endif
id_result = run_command('id', '-g', nobody_group)
if id_result.returncode() == 0
id = id_result.stdout().to_int()
if id != 65534
- message('WARNING:\n' +
- ' The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) +
- ' Your build will result in an group table setup that is incompatible with the local system.')
+ warning('\n' +
+ 'The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) +
+ 'Your build will result in an group table setup that is incompatible with the local system.')
endif
endif
if nobody_user != nobody_group and not (nobody_user == 'nobody' and nobody_group == 'nogroup')
- message('WARNING:\n' +
- ' The configured user name "@0@" and group name "@0@" of the nobody user/group are not equivalent.\n'.format(nobody_user, nobody_group) +
- ' Please re-check that both "nobody-user" and "nobody-group" options are correctly set.')
+ warning('\n' +
+ 'The configured user name "@0@" and group name "@0@" of the nobody user/group are not equivalent.\n'.format(nobody_user, nobody_group) +
+ 'Please re-check that both "nobody-user" and "nobody-group" options are correctly set.')
endif
conf.set_quoted('NOBODY_USER_NAME', nobody_user)
@@ -781,19 +738,15 @@ else
endif
substs.set('USERS_GID', users_gid)
-if get_option('adm-group')
- m4_defines += ['-DENABLE_ADM_GROUP']
-endif
-
-if get_option('wheel-group')
- m4_defines += ['-DENABLE_WHEEL_GROUP']
-endif
+conf.set10('ENABLE_ADM_GROUP', get_option('adm-group'))
+conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group'))
substs.set('DEV_KVM_MODE', get_option('dev-kvm-mode'))
substs.set('GROUP_RENDER_MODE', get_option('group-render-mode'))
kill_user_processes = get_option('default-kill-user-processes')
conf.set10('KILL_USER_PROCESSES', kill_user_processes)
+conf.set_quoted('KILL_USER_PROCESSES_YES_NO', kill_user_processes ? 'yes' : 'no')
substs.set('KILL_USER_PROCESSES', kill_user_processes ? 'yes' : 'no')
dns_servers = get_option('dns-servers')
@@ -809,23 +762,22 @@ conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
substs.set('SUSHELL', get_option('debug-shell'))
substs.set('DEBUGTTY', get_option('debug-tty'))
-debug = get_option('debug')
enable_debug_hashmap = false
enable_debug_mmap_cache = false
-if debug != ''
- foreach name : debug.split(',')
- if name == 'hashmap'
- enable_debug_hashmap = true
- elif name == 'mmap-cache'
- enable_debug_mmap_cache = true
- else
- message('unknown debug option "@0@", ignoring'.format(name))
- endif
- endforeach
-endif
+foreach name : get_option('debug')
+ if name == 'hashmap'
+ enable_debug_hashmap = true
+ elif name == 'mmap-cache'
+ enable_debug_mmap_cache = true
+ else
+ message('unknown debug option "@0@", ignoring'.format(name))
+ endif
+endforeach
conf.set10('ENABLE_DEBUG_HASHMAP', enable_debug_hashmap)
conf.set10('ENABLE_DEBUG_MMAP_CACHE', enable_debug_mmap_cache)
+conf.set10('VALGRIND', get_option('valgrind'))
+
#####################################################################
threads = dependency('threads')
@@ -841,8 +793,7 @@ if not libcap.found()
endif
libmount = dependency('mount',
- version : '>= 2.30',
- required : not fuzzer_build)
+ version : fuzzer_build ? '>= 0' : '>= 2.30')
want_seccomp = get_option('seccomp')
if want_seccomp != 'false' and not fuzzer_build
@@ -855,7 +806,6 @@ else
libseccomp = []
endif
conf.set10('HAVE_SECCOMP', have)
-m4_defines += have ? ['-DHAVE_SECCOMP'] : []
want_selinux = get_option('selinux')
if want_selinux != 'false' and not fuzzer_build
@@ -868,7 +818,6 @@ else
libselinux = []
endif
conf.set10('HAVE_SELINUX', have)
-m4_defines += have ? ['-DHAVE_SELINUX'] : []
want_apparmor = get_option('apparmor')
if want_apparmor != 'false' and not fuzzer_build
@@ -880,12 +829,10 @@ else
libapparmor = []
endif
conf.set10('HAVE_APPARMOR', have)
-m4_defines += have ? ['-DHAVE_APPARMOR'] : []
smack_run_label = get_option('smack-run-label')
if smack_run_label != ''
conf.set_quoted('SMACK_RUN_LABEL', smack_run_label)
- m4_defines += ['-DHAVE_SMACK_RUN_LABEL']
endif
want_polkit = get_option('polkit')
@@ -912,7 +859,6 @@ else
libacl = []
endif
conf.set10('HAVE_ACL', have)
-m4_defines += have ? ['-DHAVE_ACL'] : []
want_audit = get_option('audit')
if want_audit != 'false' and not fuzzer_build
@@ -957,7 +903,6 @@ else
libpam_misc = []
endif
conf.set10('HAVE_PAM', have)
-m4_defines += have ? ['-DHAVE_PAM'] : []
want_microhttpd = get_option('microhttpd')
if want_microhttpd != 'false' and not fuzzer_build
@@ -970,7 +915,6 @@ else
libmicrohttpd = []
endif
conf.set10('HAVE_MICROHTTPD', have)
-m4_defines += have ? ['-DHAVE_MICROHTTPD'] : []
want_libcryptsetup = get_option('libcryptsetup')
if want_libcryptsetup != 'false' and not fuzzer_build
@@ -995,7 +939,6 @@ else
libcurl = []
endif
conf.set10('HAVE_LIBCURL', have)
-m4_defines += have ? ['-DHAVE_LIBCURL'] : []
want_libidn = get_option('libidn')
want_libidn2 = get_option('libidn2')
@@ -1012,7 +955,6 @@ else
libidn = []
endif
conf.set10('HAVE_LIBIDN', have)
-m4_defines += have ? ['-DHAVE_LIBIDN'] : []
if not have and want_libidn2 != 'false' and not fuzzer_build
# libidn is used for both libidn and libidn2 objects
libidn = dependency('libidn2',
@@ -1022,7 +964,6 @@ else
have = false
endif
conf.set10('HAVE_LIBIDN2', have)
-m4_defines += have ? ['-DHAVE_LIBIDN2'] : []
want_libiptc = get_option('libiptc')
if want_libiptc != 'false' and not fuzzer_build
@@ -1034,7 +975,6 @@ else
libiptc = []
endif
conf.set10('HAVE_LIBIPTC', have)
-m4_defines += have ? ['-DHAVE_LIBIPTC'] : []
want_qrencode = get_option('qrencode')
if want_qrencode != 'false' and not fuzzer_build
@@ -1195,6 +1135,29 @@ conf.set('DEFAULT_DNSSEC_MODE',
'DNSSEC_' + default_dnssec.underscorify().to_upper())
substs.set('DEFAULT_DNSSEC_MODE', default_dnssec)
+dns_over_tls = get_option('dns-over-tls')
+if dns_over_tls != 'false'
+ have = conf.get('HAVE_GNUTLS') == 1
+ if dns_over_tls == 'true' and not have
+ error('DNS-over-TLS support was requested, but dependencies are not available')
+ endif
+else
+ have = false
+endif
+conf.set10('ENABLE_DNS_OVER_TLS', have)
+
+default_dns_over_tls = get_option('default-dns-over-tls')
+if fuzzer_build
+ default_dns_over_tls = 'no'
+endif
+if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0
+ message('default-dns-over-tls cannot be set to opportunistic when DNS-over-TLS support is disabled. Setting default-dns-over-tls to no.')
+ default_dns_over_tls = 'no'
+endif
+conf.set('DEFAULT_DNS_OVER_TLS_MODE',
+ 'DNS_OVER_TLS_' + default_dns_over_tls.underscorify().to_upper())
+substs.set('DEFAULT_DNS_OVER_TLS_MODE', default_dns_over_tls)
+
want_importd = get_option('importd')
if want_importd != 'false'
have = (conf.get('HAVE_LIBCURL') == 1 and
@@ -1237,6 +1200,7 @@ foreach term : ['utmp',
'hostnamed',
'localed',
'machined',
+ 'portabled',
'networkd',
'timedated',
'timesyncd',
@@ -1261,9 +1225,10 @@ foreach term : ['utmp',
have = get_option(term)
name = 'ENABLE_' + term.underscorify().to_upper()
conf.set10(name, have)
- m4_defines += have ? ['-D' + name] : []
endforeach
+conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesyncd'))
+
want_tests = get_option('tests')
install_tests = get_option('install-tests')
slow_tests = get_option('slow-tests')
@@ -1309,12 +1274,17 @@ config_h = configure_file(
output : 'config.h',
configuration : conf)
+meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
+
includes = include_directories('src/basic',
'src/shared',
'src/systemd',
'src/journal',
+ 'src/journal-remote',
+ 'src/nspawn',
'src/resolve',
'src/timesync',
+ 'src/time-wait-sync',
'src/login',
'src/udev',
'src/libudev',
@@ -1366,6 +1336,31 @@ libsystemd = shared_library(
install : true,
install_dir : rootlibdir)
+static_libsystemd = get_option('static-libsystemd')
+static_libsystemd_pic = static_libsystemd == 'true' or static_libsystemd == 'pic'
+
+install_libsystemd_static = static_library(
+ 'systemd',
+ libsystemd_sources,
+ journal_client_sources,
+ basic_sources,
+ basic_gcrypt_sources,
+ include_directories : includes,
+ build_by_default : static_libsystemd != 'false',
+ install : static_libsystemd != 'false',
+ install_dir : rootlibdir,
+ pic : static_libsystemd == 'true' or static_libsystemd == 'pic',
+ dependencies : [threads,
+ librt,
+ libxz,
+ liblz4,
+ libcap,
+ libblkid,
+ libmount,
+ libselinux,
+ libgcrypt],
+ c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC']))
+
############################################################
# binaries that have --help and are intended for use by humans,
@@ -1386,6 +1381,7 @@ subdir('src/import')
subdir('src/kernel-install')
subdir('src/locale')
subdir('src/machine')
+subdir('src/portable')
subdir('src/nspawn')
subdir('src/resolve')
subdir('src/timedate')
@@ -1609,16 +1605,13 @@ if conf.get('ENABLE_RESOLVE') == 1
link_with : [libshared,
libbasic_gcrypt,
libsystemd_resolve_core],
- dependencies : [threads,
- libgpg_error,
- libm,
- libidn],
+ dependencies : systemd_resolved_dependencies,
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
- exe = executable('systemd-resolve',
- systemd_resolve_sources,
+ exe = executable('resolvectl',
+ resolvectl_sources,
include_directories : includes,
link_with : [libshared,
libbasic_gcrypt,
@@ -1630,6 +1623,14 @@ if conf.get('ENABLE_RESOLVE') == 1
install_rpath : rootlibexecdir,
install : true)
public_programs += [exe]
+
+ meson.add_install_script(meson_make_symlink,
+ join_paths(bindir, 'resolvectl'),
+ join_paths(rootsbindir, 'resolvconf'))
+
+ meson.add_install_script(meson_make_symlink,
+ join_paths(bindir, 'resolvectl'),
+ join_paths(bindir, 'systemd-resolve'))
endif
if conf.get('ENABLE_LOGIND') == 1
@@ -1689,6 +1690,14 @@ if conf.get('ENABLE_LOGIND') == 1
endif
endif
+executable('systemd-user-runtime-dir',
+ user_runtime_dir_sources,
+ include_directories : includes,
+ link_with : [libshared, liblogind_core],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootlibexecdir)
+
if conf.get('HAVE_PAM') == 1
executable('systemd-user-sessions',
'src/user-sessions/user-sessions.c',
@@ -1718,9 +1727,19 @@ exe = executable('systemd-socket-activate', 'src/activate/activate.c',
install : true)
public_programs += [exe]
+
+if get_option('link-systemctl-shared')
+ systemctl_link_with = [libshared]
+else
+ systemctl_link_with = [libsystemd_static,
+ libshared_static,
+ libjournal_client,
+ libbasic_gcrypt]
+endif
+
exe = executable('systemctl', 'src/systemctl/systemctl.c',
include_directories : includes,
- link_with : [libshared],
+ link_with : systemctl_link_with,
dependencies : [threads,
libcap,
libselinux,
@@ -1731,6 +1750,26 @@ exe = executable('systemctl', 'src/systemctl/systemctl.c',
install_dir : rootbindir)
public_programs += [exe]
+if conf.get('ENABLE_PORTABLED') == 1
+ executable('systemd-portabled',
+ systemd_portabled_sources,
+ include_directories : includes,
+ link_with : [libshared],
+ dependencies : [threads],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootlibexecdir)
+
+ exe = executable('portablectl', 'src/portable/portablectl.c',
+ include_directories : includes,
+ link_with : [libshared],
+ dependencies : [threads],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootlibexecdir)
+ public_programs += [exe]
+endif
+
foreach alias : ['halt', 'poweroff', 'reboot', 'runlevel', 'shutdown', 'telinit']
meson.add_install_script(meson_make_symlink,
join_paths(rootbindir, 'systemctl'),
@@ -1873,12 +1912,15 @@ if conf.get('ENABLE_TIMEDATED') == 1
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
+endif
+if conf.get('ENABLE_TIMEDATECTL') == 1
exe = executable('timedatectl',
'src/timedate/timedatectl.c',
include_directories : includes,
install_rpath : rootlibexecdir,
link_with : [libshared],
+ dependencies : [libm],
install : true)
public_programs += [exe]
endif
@@ -1893,6 +1935,14 @@ if conf.get('ENABLE_TIMESYNCD') == 1
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
+
+ executable('systemd-time-wait-sync',
+ 'src/time-wait-sync/time-wait-sync.c',
+ include_directories : includes,
+ link_with : [libshared],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootlibexecdir)
endif
if conf.get('ENABLE_MACHINED') == 1
@@ -1987,7 +2037,8 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1
s_j_remote = executable('systemd-journal-remote',
systemd_journal_remote_sources,
include_directories : includes,
- link_with : [libshared],
+ link_with : [libshared,
+ libsystemd_journal_remote],
dependencies : [threads,
libmicrohttpd,
libgnutls,
@@ -2398,6 +2449,7 @@ executable('systemd-shutdown',
systemd_shutdown_sources,
include_directories : includes,
link_with : [libshared],
+ dependencies : [libmount],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
@@ -2441,12 +2493,10 @@ exe = executable('systemd-nspawn',
'src/core/mount-setup.h',
'src/core/loopback-setup.c',
'src/core/loopback-setup.h',
- include_directories : [includes, include_directories('src/nspawn')],
- link_with : [libshared],
- dependencies : [libacl,
- libblkid,
- libseccomp,
- libselinux],
+ include_directories : includes,
+ link_with : [libnspawn_core,
+ libshared],
+ dependencies : [libblkid],
install_rpath : rootlibexecdir,
install : true)
public_programs += [exe]
@@ -2537,17 +2587,30 @@ foreach tuple : tests
endif
endforeach
-test_libsystemd_sym = executable(
+exe = executable(
'test-libsystemd-sym',
test_libsystemd_sym_c,
include_directories : includes,
link_with : [libsystemd],
install : install_tests,
install_dir : testsdir)
-test('test-libsystemd-sym',
- test_libsystemd_sym)
+test('test-libsystemd-sym', exe)
-test_libudev_sym = executable(
+exe = executable(
+ 'test-libsystemd-static-sym',
+ test_libsystemd_sym_c,
+ include_directories : includes,
+ link_with : [install_libsystemd_static],
+ dependencies : [threads], # threads is already included in dependencies on the library,
+ # but does not seem to get propagated. Add here as a work-around.
+ build_by_default : static_libsystemd_pic,
+ install : install_tests and static_libsystemd_pic,
+ install_dir : testsdir)
+if static_libsystemd_pic
+ test('test-libsystemd-static-sym', exe)
+endif
+
+exe = executable(
'test-libudev-sym',
test_libudev_sym_c,
include_directories : includes,
@@ -2555,8 +2618,20 @@ test_libudev_sym = executable(
link_with : [libudev],
install : install_tests,
install_dir : testsdir)
-test('test-libudev-sym',
- test_libudev_sym)
+test('test-libudev-sym', exe)
+
+exe = executable(
+ 'test-libudev-static-sym',
+ test_libudev_sym_c,
+ include_directories : includes,
+ c_args : ['-Wno-deprecated-declarations'],
+ link_with : [install_libudev_static],
+ build_by_default : static_libudev_pic,
+ install : install_tests and static_libudev_pic,
+ install_dir : testsdir)
+if static_libudev_pic
+ test('test-libudev-static-sym', exe)
+endif
############################################################
@@ -2608,8 +2683,8 @@ subdir('network')
subdir('man')
subdir('shell-completion/bash')
subdir('shell-completion/zsh')
-subdir('docs/sysvinit')
-subdir('docs/var-log')
+subdir('doc/sysvinit')
+subdir('doc/var-log')
# FIXME: figure out if the warning is true:
# https://github.com/mesonbuild/meson/wiki/Reference-manual#install_subdir
@@ -2651,48 +2726,56 @@ endforeach
############################################################
-prev = ''
-foreach p : fuzz_regression_tests
- a = p.split('/')[-3]
- b = p.split('/')[-2]
- c = p.split('/')[-1]
-
- if a == 'address'
- build = sanitize_address
- else
- error('unknown sanitizer @0@'.format(a))
- endif
+# Enable tests for all supported sanitizers
+foreach tuple : sanitizers
+ sanitizer = tuple[0]
+ build = tuple[1]
- name = '@1@:@0@'.format(a, b)
-
- if name != prev
- if want_tests == 'false'
- message('Not compiling @0@ because tests is set to false'.format(name))
- elif not sanitizers.contains(a)
- message('Not compiling @0@ because @1@ sanitizer is not available'.format(name, a))
- elif slow_tests
- exe = custom_target(
- name,
- output : name,
- depends : build,
- command : [env, 'ln', '-fs',
- join_paths(build.full_path(), b),
- '@OUTPUT@'],
- build_by_default : true)
- else
- message('Not compiling @0@ because slow-tests is set to false'.format(name))
- endif
- endif
- prev = name
+ have = run_command(check_compilation_sh,
+ cc.cmd_array(), '-x', 'c',
+ '-fsanitize=@0@'.format(sanitizer),
+ '-include', link_test_c).returncode() == 0
+ message('@0@ sanitizer supported: @1@'.format(sanitizer, have ? 'yes' : 'no'))
- if want_tests != 'false' and slow_tests
- test(c, env, args : [exe.full_path(),
- join_paths(meson.source_root(),
- 'test/fuzz-regressions',
- p)])
+ if have
+ prev = ''
+ foreach p : fuzz_regression_tests
+ b = p.split('/')[-2]
+ c = p.split('/')[-1]
+
+ name = '@0@:@1@'.format(b, sanitizer)
+
+ if name != prev
+ if want_tests == 'false'
+ message('Not compiling @0@ because tests is set to false'.format(name))
+ elif slow_tests
+ exe = custom_target(
+ name,
+ output : name,
+ depends : build,
+ command : [env, 'ln', '-fs',
+ join_paths(build.full_path(), b),
+ '@OUTPUT@'],
+ build_by_default : true)
+ else
+ message('Not compiling @0@ because slow-tests is set to false'.format(name))
+ endif
+ endif
+ prev = name
+
+ if want_tests != 'false' and slow_tests
+ test('@0@:@1@:@2@'.format(b, c, sanitizer),
+ env,
+ args : [exe.full_path(),
+ join_paths(meson.source_root(),
+ 'test/fuzz-regressions',
+ p)])
+ endif
+ endforeach
endif
endforeach
+
############################################################
if git.found()
@@ -2707,9 +2790,8 @@ if git.found()
'tags',
output : 'tags',
command : [env, 'etags', '-o', '@0@/TAGS'.format(meson.current_source_dir())] + all_files)
- custom_target(
+ run_target(
'ctags',
- output : 'ctags',
command : [env, 'ctags', '-o', '@0@/tags'.format(meson.current_source_dir())] + all_files)
endif
@@ -2793,6 +2875,7 @@ status = [
'symbolic gateway hostnames: @0@'.format(', '.join(gateway_hostnames)),
'default DNSSEC mode: @0@'.format(default_dnssec),
+ 'default DNS-over-TLS mode: @0@'.format(default_dns_over_tls),
'default cgroup hierarchy: @0@'.format(default_hierarchy),
'default KillUserProcesses setting: @0@'.format(kill_user_processes)]
@@ -2866,6 +2949,7 @@ foreach tuple : [
['rfkill'],
['logind'],
['machined'],
+ ['portabled'],
['importd'],
['hostnamed'],
['timedated'],
@@ -2873,6 +2957,7 @@ foreach tuple : [
['localed'],
['networkd'],
['resolve'],
+ ['DNS-over-TLS'],
['coredump'],
['polkit'],
['legacy pkla', install_polkit_pkla],
@@ -2899,6 +2984,7 @@ foreach tuple : [
['gshadow'],
['debug hashmap'],
['debug mmap cache'],
+ ['valgrind', conf.get('VALGRIND') == 1],
]
if tuple.length() >= 2
@@ -2924,8 +3010,8 @@ status += [
message('\n '.join(status))
if rootprefixdir != rootprefix_default
- message('WARNING:\n' +
- ' Note that the installation prefix was changed to "@0@".\n'.format(rootprefixdir) +
- ' systemd used fixed names for unit file directories and other paths, so anything\n' +
- ' except the default ("@0@") is strongly discouraged.'.format(rootprefix_default))
+ warning('\n' +
+ 'Note that the installation prefix was changed to "@0@".\n'.format(rootprefixdir) +
+ 'systemd used fixed names for unit file directories and other paths, so anything\n' +
+ 'except the default ("@0@") is strongly discouraged.'.format(rootprefix_default))
endif
diff --git a/meson_options.txt b/meson_options.txt
index 4efb422f90..16c1f2b2fa 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,20 +1,5 @@
# -*- mode: meson -*-
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
option('split-usr', type : 'combo', choices : ['auto', 'true', 'false'],
description : '''/bin, /sbin aren't symlinks into /usr''')
@@ -26,6 +11,14 @@ option('rootprefix', type : 'string',
description : '''override the root prefix''')
option('link-udev-shared', type : 'boolean',
description : 'link systemd-udev and its helpers to libsystemd-shared.so')
+option('link-systemctl-shared', type: 'boolean',
+ description : 'link systemctl against libsystemd-shared.so')
+option('static-libsystemd', type : 'combo',
+ choices : ['false', 'true', 'pic', 'no-pic'],
+ description : '''install a static library for libsystemd''')
+option('static-libudev', type : 'combo',
+ choices : ['false', 'true', 'pic', 'no-pic'],
+ description : '''install a static library for libudev''')
option('sysvinit-path', type : 'string', value : '/etc/init.d',
description : 'the directory where the SysV init scripts are located')
@@ -53,10 +46,12 @@ option('debug-shell', type : 'string', value : '/bin/sh',
description : 'path to debug shell binary')
option('debug-tty', type : 'string', value : '/dev/tty9',
description : 'specify the tty device for debug shell')
-option('debug', type : 'string',
- description : 'enable extra debugging (hashmap,mmap-cache)')
+option('debug', type : 'array', choices : ['hashmap', 'mmap-cache'], value : [],
+ description : 'enable extra debugging')
option('memory-accounting-default', type : 'boolean',
description : 'enable MemoryAccounting= by default')
+option('valgrind', type : 'boolean', value : false,
+ description : 'do extra operations to avoid valgrind warnings')
option('utmp', type : 'boolean',
description : 'support for utmp/wtmp log handling')
@@ -84,6 +79,8 @@ option('localed', type : 'boolean',
description : 'install the systemd-localed stack')
option('machined', type : 'boolean',
description : 'install the systemd-machined stack')
+option('portabled', type : 'boolean',
+ description : 'install the systemd-portabled stack')
option('networkd', type : 'boolean',
description : 'install the systemd-networkd stack')
option('timedated', type : 'boolean',
@@ -194,6 +191,12 @@ option('default-dnssec', type : 'combo',
description : 'default DNSSEC mode',
choices : ['yes', 'allow-downgrade', 'no'],
value : 'allow-downgrade')
+option('default-dns-over-tls', type : 'combo',
+ description : 'default DNS-over-TLS mode',
+ choices : ['opportunistic', 'no'],
+ value : 'no')
+option('dns-over-tls', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'DNS-over-TLS support')
option('dns-servers', type : 'string',
description : 'space-separated list of default DNS servers',
value : '8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844')
diff --git a/mkosi.build b/mkosi.build
index 7cdcd6c741..b7b8c50a2b 100755
--- a/mkosi.build
+++ b/mkosi.build
@@ -1,26 +1,17 @@
#!/bin/sh
set -ex
-# This file is part of systemd.
-#
-# Copyright 2016 Lennart Poettering
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
# This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi).
# Simply invoke "mkosi" in the project directory to build an OS image.
+# Reset the permissions of the tree. Since Meson keeps the permissions
+# all the way to the installed files, reset them to one of 0644 or 0755
+# so the files keep those permissions, otherwise details of what umask
+# was set at the time the git tree was cloned will leak all the way
+# through. Also set umask explicitly during the build.
+chmod -R u+w,go-w,a+rX .
+umask 022
+
# If mkosi.builddir/ exists mkosi will set $BUILDDIR to it, let's then use it
# as out-of-tree build dir. Otherwise, let's make up our own builddir.
[ -z "$BUILDDIR" ] && BUILDDIR=build
@@ -89,7 +80,7 @@ if [ ! -f "$BUILDDIR"/build.ninja ] ; then
fi
ninja -C "$BUILDDIR" all
-[ "$WITH_TESTS" = 0 ] || ninja -C "$BUILDDIR" test || ( RET="$?" ; cat "$BUILDDIR"/meson-logs/testlog.txt ; exit "$RET" )
+[ "$WITH_TESTS" = 0 ] || ninja -C "$BUILDDIR" test
ninja -C "$BUILDDIR" install
mkdir -p "$DESTDIR"/etc
diff --git a/network/meson.build b/network/meson.build
index fb17e1632e..59d4be1a17 100644
--- a/network/meson.build
+++ b/network/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
if conf.get('ENABLE_NETWORKD') == 1
install_data('80-container-host0.network',
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 470829acae..029261c154 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,6 +4,7 @@ src/import/org.freedesktop.import1.policy
src/locale/org.freedesktop.locale1.policy
src/login/org.freedesktop.login1.policy
src/machine/org.freedesktop.machine1.policy
+src/portable/org.freedesktop.portable1.policy
src/resolve/org.freedesktop.resolve1.policy
src/timedate/org.freedesktop.timedate1.policy
src/core/dbus-unit.c
diff --git a/po/be.po b/po/be.po
index ce8f1223cd..a74b9a3cea 100644
--- a/po/be.po
+++ b/po/be.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Belarusian translation for systemd.
-# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
#
#
diff --git a/po/be@latin.po b/po/be@latin.po
index 36eb347ae1..5085459623 100644
--- a/po/be@latin.po
+++ b/po/be@latin.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Belarusian translation for systemd.
-# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
#
#
diff --git a/po/bg.po b/po/bg.po
index b395cc2ca7..3e3cda15ff 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Bulgarian translation of systemd po-file.
-# Copyright (C) 2016 Alexander Shopov <ash@kambanaria.org>
+# Copyright © 2016 Alexander Shopov <ash@kambanaria.org>
# This file is distributed under the same license as the systemd package.
# Alexander Shopov <ash@kambanaria.org>, 2016.
#
diff --git a/po/ca.po b/po/ca.po
index 13b3b1a455..8f1ef8f2d1 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Catalan translation for systemd.
-# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Walter Garcia-Fontes <walter.garcia@upf.edu>, 2016.
# Robert Antoni Buj Gelonch <rbuj@fedoraproject.org>, 2018. #zanata
diff --git a/po/cs.po b/po/cs.po
index b1227ff411..7589d7ce37 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Czech translation for systemd.
-# Copyright (C) 2016-2017 systemd's author and translators.
# This file is distributed under the same license as the systemd package.
# Daniel Maixner <xskipy@gmail.com>, 2016.
# Daniel Rusek <mail@asciiwolf.com>, 2016, 2017.
diff --git a/po/da.po b/po/da.po
index 187103ce9e..20032945a9 100644
--- a/po/da.po
+++ b/po/da.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Danish translation for systemd.
-# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Daniel Machon <dmachon.dev@gmail.com>, 2015.
#
diff --git a/po/de.po b/po/de.po
index bb431fe4a7..c3d15c929a 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# German translation for systemd.
-# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Christian Kirbach <Christian.Kirbach@gmail.com>, 2014, 2015.
# Benjamin Steinwender <b@stbe.at>, 2014.
diff --git a/po/el.po b/po/el.po
index 0e7db7fb15..f4d9560af9 100644
--- a/po/el.po
+++ b/po/el.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Greek translation for systemd.
-# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Dimitris Spingos <dmtrs32@gmail.com>, 2014.
# Dimitris Spingos (Δημήτρης Σπίγγος) <dmtrs32@gmail.com>, 2014.
diff --git a/po/es.po b/po/es.po
index 705a47e354..22cdb40fc7 100644
--- a/po/es.po
+++ b/po/es.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Spanish translation for systemd.
-# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Alex Puchades <alex94puchades@gmail.com>, 2015.
# Daniel Mustieles <daniel.mustieles@gmail.com>, 2015.
diff --git a/po/fr.po b/po/fr.po
index 902c5da48d..284fcca9b0 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -3,14 +3,14 @@
# French translations for systemd package
# Traductions françaises du paquet systemd.
# This file is distributed under the same license as the systemd package.
-# Sylvain Plantefève <sylvain.plantefeve@gmail.com>, 2013-2017
+# Sylvain Plantefève <sylvain.plantefeve@gmail.com>, 2013-2018
#
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-02-13 20:30+0100\n"
-"PO-Revision-Date: 2018-02-13 21:45+0200\n"
+"POT-Creation-Date: 2018-06-19 20:57+0200\n"
+"PO-Revision-Date: 2018-05-29 21:24+0200\n"
"Last-Translator: Sylvain Plantefève <sylvain.plantefeve@gmail.com>\n"
"Language-Team: French\n"
"Language: fr\n"
@@ -19,41 +19,41 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: src/core/org.freedesktop.systemd1.policy.in.in:22
+#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
msgstr "Renvoyer la phrase secrète au système"
-#: src/core/org.freedesktop.systemd1.policy.in.in:23
+#: src/core/org.freedesktop.systemd1.policy.in:23
msgid ""
"Authentication is required to send the entered passphrase back to the system."
msgstr "Authentification requise pour renvoyer la phrase secrète au système."
-#: src/core/org.freedesktop.systemd1.policy.in.in:33
+#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
msgstr "Gérer les services système ou les unités"
-#: src/core/org.freedesktop.systemd1.policy.in.in:34
+#: src/core/org.freedesktop.systemd1.policy.in:34
msgid "Authentication is required to manage system services or other units."
msgstr ""
"Authentification requise pour gérer les services système ou les unités."
-#: src/core/org.freedesktop.systemd1.policy.in.in:43
+#: src/core/org.freedesktop.systemd1.policy.in:43
msgid "Manage system service or unit files"
msgstr "Gérer le service système ou ses fichiers unités"
-#: src/core/org.freedesktop.systemd1.policy.in.in:44
+#: src/core/org.freedesktop.systemd1.policy.in:44
msgid "Authentication is required to manage system service or unit files."
msgstr ""
"Authentification requise pour gérer le service système ou ses fichiers "
"unités."
-#: src/core/org.freedesktop.systemd1.policy.in.in:53
+#: src/core/org.freedesktop.systemd1.policy.in:54
msgid "Set or unset system and service manager environment variables"
msgstr ""
"Définir ou supprimer des variables d'environnement du système ou du "
"gestionnaire de services"
-#: src/core/org.freedesktop.systemd1.policy.in.in:54
+#: src/core/org.freedesktop.systemd1.policy.in:55
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
@@ -61,27 +61,27 @@ msgstr ""
"Authentification requise pour définir ou supprimer des variables "
"d'environnement du système ou du gestionnaire de services."
-#: src/core/org.freedesktop.systemd1.policy.in.in:63
+#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Reload the systemd state"
msgstr "Recharger l'état de systemd"
-#: src/core/org.freedesktop.systemd1.policy.in.in:64
+#: src/core/org.freedesktop.systemd1.policy.in:65
msgid "Authentication is required to reload the systemd state."
msgstr "Authentification requise pour recharger l'état de systemd"
-#: src/hostname/org.freedesktop.hostname1.policy.in:22
+#: src/hostname/org.freedesktop.hostname1.policy:20
msgid "Set host name"
msgstr "Définir le nom d'hôte"
-#: src/hostname/org.freedesktop.hostname1.policy.in:23
+#: src/hostname/org.freedesktop.hostname1.policy:21
msgid "Authentication is required to set the local host name."
msgstr "Authentification requise pour définir le nom d'hôte local."
-#: src/hostname/org.freedesktop.hostname1.policy.in:32
+#: src/hostname/org.freedesktop.hostname1.policy:30
msgid "Set static host name"
msgstr "Définir le nom d'hôte statique"
-#: src/hostname/org.freedesktop.hostname1.policy.in:33
+#: src/hostname/org.freedesktop.hostname1.policy:31
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
@@ -89,109 +89,109 @@ msgstr ""
"Authentification requise pour définir le nom d'hôte local de manière "
"statique, tout comme le nom d'hôte familier."
-#: src/hostname/org.freedesktop.hostname1.policy.in:43
+#: src/hostname/org.freedesktop.hostname1.policy:41
msgid "Set machine information"
msgstr "Définir les informations sur la machine"
-#: src/hostname/org.freedesktop.hostname1.policy.in:44
+#: src/hostname/org.freedesktop.hostname1.policy:42
msgid "Authentication is required to set local machine information."
msgstr ""
"Authentification requise pour définir les informations sur la machine locale."
-#: src/import/org.freedesktop.import1.policy.in:22
+#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
msgstr "Importer une image de machine virtuelle (VM) ou de conteneur"
-#: src/import/org.freedesktop.import1.policy.in:23
+#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
msgstr ""
"Authentification requise pour importer une image de machine virtuelle (VM) "
"ou de conteneur."
-#: src/import/org.freedesktop.import1.policy.in:32
+#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
msgstr "Exporter une image de machine virtuelle (VM) ou de conteneur"
-#: src/import/org.freedesktop.import1.policy.in:33
+#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
msgstr ""
"Authentification requise pour exporter une image de machine virtuelle (VM) "
"ou de conteneur."
-#: src/import/org.freedesktop.import1.policy.in:42
+#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
msgstr "Télécharger une image de machine virtuelle (VM) ou de conteneur"
-#: src/import/org.freedesktop.import1.policy.in:43
+#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
msgstr ""
"Authentification requise pour télécharger une image de machine virtuelle "
"(VM) ou de conteneur."
-#: src/locale/org.freedesktop.locale1.policy.in:22
+#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
msgstr "Définir la langue du système"
-#: src/locale/org.freedesktop.locale1.policy.in:23
+#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
msgstr "Authentification requise pour définir la langue du système."
-#: src/locale/org.freedesktop.locale1.policy.in:33
+#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
msgstr "Définir les paramètres de clavier du système"
-#: src/locale/org.freedesktop.locale1.policy.in:34
+#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
msgstr ""
"Authentification requise pour définir les paramètres de clavier du système."
-#: src/login/org.freedesktop.login1.policy.in:22
+#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
msgstr "Permet aux applications d'empêcher l'arrêt du système"
-#: src/login/org.freedesktop.login1.policy.in:23
+#: src/login/org.freedesktop.login1.policy:23
msgid ""
"Authentication is required for an application to inhibit system shutdown."
msgstr ""
"Authentification requise pour permettre à une application d'empêcher l'arrêt "
"du système."
-#: src/login/org.freedesktop.login1.policy.in:33
+#: src/login/org.freedesktop.login1.policy:33
msgid "Allow applications to delay system shutdown"
msgstr "Permet aux applications de retarder l'arrêt du système"
-#: src/login/org.freedesktop.login1.policy.in:34
+#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
msgstr ""
"Authentification requise pour permettre à une application de retarder "
"l'arrêt du système."
-#: src/login/org.freedesktop.login1.policy.in:44
+#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
msgstr "Permet aux applications d'empêcher la mise en veille du système"
-#: src/login/org.freedesktop.login1.policy.in:45
+#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr ""
"Authentification requise pour permettre à une application d'empêcher la mise "
"en veille du système."
-#: src/login/org.freedesktop.login1.policy.in:55
+#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"
msgstr "Permet aux applications de retarder la mise en veille du système"
-#: src/login/org.freedesktop.login1.policy.in:56
+#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
msgstr ""
"Authentification requise pour permettre à une application de retarder la "
"mise en veille du système."
-#: src/login/org.freedesktop.login1.policy.in:65
+#: src/login/org.freedesktop.login1.policy:65
msgid "Allow applications to inhibit automatic system suspend"
msgstr ""
"Permet aux applications d'empêcher l'hibernation automatique du système"
-#: src/login/org.freedesktop.login1.policy.in:66
+#: src/login/org.freedesktop.login1.policy:66
msgid ""
"Authentication is required for an application to inhibit automatic system "
"suspend."
@@ -199,13 +199,13 @@ msgstr ""
"Authentification requise pour permettre à une application d'empêcher "
"l'hibernation automatique du système."
-#: src/login/org.freedesktop.login1.policy.in:75
+#: src/login/org.freedesktop.login1.policy:75
msgid "Allow applications to inhibit system handling of the power key"
msgstr ""
"Permet aux applications d'empêcher la gestion du bouton d'alimentation du "
"système"
-#: src/login/org.freedesktop.login1.policy.in:76
+#: src/login/org.freedesktop.login1.policy:76
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the power key."
@@ -213,13 +213,13 @@ msgstr ""
"Authentification requise pour permettre à une application d'empêcher la "
"gestion du bouton d'alimentation du système."
-#: src/login/org.freedesktop.login1.policy.in:86
+#: src/login/org.freedesktop.login1.policy:86
msgid "Allow applications to inhibit system handling of the suspend key"
msgstr ""
"Permet aux applications d'empêcher la gestion du bouton de mise en veille du "
"système"
-#: src/login/org.freedesktop.login1.policy.in:87
+#: src/login/org.freedesktop.login1.policy:87
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
@@ -227,13 +227,13 @@ msgstr ""
"Authentification requise pour permettre à une application d'empêcher la "
"gestion du bouton de mise en veille du système."
-#: src/login/org.freedesktop.login1.policy.in:97
+#: src/login/org.freedesktop.login1.policy:97
msgid "Allow applications to inhibit system handling of the hibernate key"
msgstr ""
"Permet aux applications d'empêcher la gestion du bouton d'hibernation du "
"système"
-#: src/login/org.freedesktop.login1.policy.in:98
+#: src/login/org.freedesktop.login1.policy:98
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
@@ -241,13 +241,13 @@ msgstr ""
"Authentification requise pour permettre à une application d'empêcher la "
"gestion du bouton d'hibernation du système."
-#: src/login/org.freedesktop.login1.policy.in:107
+#: src/login/org.freedesktop.login1.policy:107
msgid "Allow applications to inhibit system handling of the lid switch"
msgstr ""
"Permet aux applications d'empêcher la gestion par le système du rabat de "
"l'écran"
-#: src/login/org.freedesktop.login1.policy.in:108
+#: src/login/org.freedesktop.login1.policy:108
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
@@ -255,59 +255,59 @@ msgstr ""
"Authentification requise pour permettre à une application d'empêcher la "
"gestion par le système du rabat de l'écran."
-#: src/login/org.freedesktop.login1.policy.in:117
+#: src/login/org.freedesktop.login1.policy:117
msgid "Allow non-logged-in user to run programs"
msgstr "Permet à un utilisateur non connecté d'exécuter des programmes"
-#: src/login/org.freedesktop.login1.policy.in:118
+#: src/login/org.freedesktop.login1.policy:118
msgid "Explicit request is required to run programs as a non-logged-in user."
msgstr ""
"Requête explicite requise pour exécuter des programmes en tant "
"qu'utilisateur non connecté."
-#: src/login/org.freedesktop.login1.policy.in:127
+#: src/login/org.freedesktop.login1.policy:127
msgid "Allow non-logged-in users to run programs"
msgstr "Permet aux utilisateurs non connectés d'exécuter des programmes"
-#: src/login/org.freedesktop.login1.policy.in:128
+#: src/login/org.freedesktop.login1.policy:128
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
"Authentification requise pour exécuter des programmes en tant qu'utilisateur "
"non connecté."
-#: src/login/org.freedesktop.login1.policy.in:137
+#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
msgstr "Permet d'associer des périphériques à des postes (seats)"
-#: src/login/org.freedesktop.login1.policy.in:138
+#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required for attaching a device to a seat."
msgstr ""
"Authentification requise pour associer un périphérique à un poste (seat)."
-#: src/login/org.freedesktop.login1.policy.in:148
+#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
msgstr "Révoquer les associations de périphériques aux postes (seats)"
-#: src/login/org.freedesktop.login1.policy.in:149
+#: src/login/org.freedesktop.login1.policy:149
msgid ""
"Authentication is required for resetting how devices are attached to seats."
msgstr ""
"Authentification requise pour révoquer les associations de périphériques aux "
"postes (seats)."
-#: src/login/org.freedesktop.login1.policy.in:158
+#: src/login/org.freedesktop.login1.policy:158
msgid "Power off the system"
msgstr "Éteindre le système"
-#: src/login/org.freedesktop.login1.policy.in:159
+#: src/login/org.freedesktop.login1.policy:159
msgid "Authentication is required for powering off the system."
msgstr "Authentification requise pour éteindre le système."
-#: src/login/org.freedesktop.login1.policy.in:169
+#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system while other users are logged in"
msgstr "Éteindre le système alors que d'autres utilisateurs sont connectés"
-#: src/login/org.freedesktop.login1.policy.in:170
+#: src/login/org.freedesktop.login1.policy:170
msgid ""
"Authentication is required for powering off the system while other users are "
"logged in."
@@ -315,11 +315,11 @@ msgstr ""
"Authentification requise pour éteindre le système alors que d'autres "
"utilisateurs sont connectés."
-#: src/login/org.freedesktop.login1.policy.in:180
+#: src/login/org.freedesktop.login1.policy:180
msgid "Power off the system while an application asked to inhibit it"
msgstr "Éteindre le système alors qu'une application a demandé de l'empêcher"
-#: src/login/org.freedesktop.login1.policy.in:181
+#: src/login/org.freedesktop.login1.policy:181
msgid ""
"Authentication is required for powering off the system while an application "
"asked to inhibit it."
@@ -327,19 +327,19 @@ msgstr ""
"Authentification requise pour éteindre le système alors qu'une application a "
"demandé de l'empêcher."
-#: src/login/org.freedesktop.login1.policy.in:191
+#: src/login/org.freedesktop.login1.policy:191
msgid "Reboot the system"
msgstr "Redémarrer le système"
-#: src/login/org.freedesktop.login1.policy.in:192
+#: src/login/org.freedesktop.login1.policy:192
msgid "Authentication is required for rebooting the system."
msgstr "Authentification requise pour redémarrer le système."
-#: src/login/org.freedesktop.login1.policy.in:202
+#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system while other users are logged in"
msgstr "Redémarrer le système alors que d'autres utilisateurs sont connectés"
-#: src/login/org.freedesktop.login1.policy.in:203
+#: src/login/org.freedesktop.login1.policy:203
msgid ""
"Authentication is required for rebooting the system while other users are "
"logged in."
@@ -347,11 +347,11 @@ msgstr ""
"Authentification requise pour redémarrer le système alors que d'autres "
"utilisateurs sont connectés."
-#: src/login/org.freedesktop.login1.policy.in:213
+#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while an application asked to inhibit it"
msgstr "Redémarrer le système alors qu'une application a demandé de l'empêcher"
-#: src/login/org.freedesktop.login1.policy.in:214
+#: src/login/org.freedesktop.login1.policy:214
msgid ""
"Authentication is required for rebooting the system while an application "
"asked to inhibit it."
@@ -359,19 +359,19 @@ msgstr ""
"Authentification requise pour redémarrer le système alors qu'une application "
"a demandé de l'empêcher."
-#: src/login/org.freedesktop.login1.policy.in:224
+#: src/login/org.freedesktop.login1.policy:224
msgid "Halt the system"
msgstr "Arrêter le système"
-#: src/login/org.freedesktop.login1.policy.in:225
+#: src/login/org.freedesktop.login1.policy:225
msgid "Authentication is required for halting the system."
msgstr "Authentification requise pour arrêter le système."
-#: src/login/org.freedesktop.login1.policy.in:235
+#: src/login/org.freedesktop.login1.policy:235
msgid "Halt the system while other users are logged in"
msgstr "Arrêter le système alors que d'autres utilisateurs sont connectés"
-#: src/login/org.freedesktop.login1.policy.in:236
+#: src/login/org.freedesktop.login1.policy:236
msgid ""
"Authentication is required for halting the system while other users are "
"logged in."
@@ -379,11 +379,11 @@ msgstr ""
"Authentification requise pour arrêter le système alors que d'autres "
"utilisateurs sont connectés."
-#: src/login/org.freedesktop.login1.policy.in:246
+#: src/login/org.freedesktop.login1.policy:246
msgid "Halt the system while an application asked to inhibit it"
msgstr "Arrêter le système alors qu'une application a demandé de l'empêcher"
-#: src/login/org.freedesktop.login1.policy.in:247
+#: src/login/org.freedesktop.login1.policy:247
msgid ""
"Authentication is required for halting the system while an application asked "
"to inhibit it."
@@ -391,20 +391,20 @@ msgstr ""
"Authentification requise pour arrêter le système alors qu'une application a "
"demandé de l'empêcher."
-#: src/login/org.freedesktop.login1.policy.in:257
+#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
msgstr "Mettre le système en veille"
-#: src/login/org.freedesktop.login1.policy.in:258
+#: src/login/org.freedesktop.login1.policy:258
msgid "Authentication is required for suspending the system."
msgstr "Authentification requise pour mettre le système en veille."
-#: src/login/org.freedesktop.login1.policy.in:267
+#: src/login/org.freedesktop.login1.policy:267
msgid "Suspend the system while other users are logged in"
msgstr ""
"Mettre le système en veille alors que d'autres utilisateurs sont connectés"
-#: src/login/org.freedesktop.login1.policy.in:268
+#: src/login/org.freedesktop.login1.policy:268
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
@@ -412,12 +412,12 @@ msgstr ""
"Authentification requise pour mettre le système en veille alors que d'autres "
"utilisateurs sont connectés."
-#: src/login/org.freedesktop.login1.policy.in:278
+#: src/login/org.freedesktop.login1.policy:278
msgid "Suspend the system while an application asked to inhibit it"
msgstr ""
"Mettre le système en veille alors qu'une application a demandé de l'empêcher"
-#: src/login/org.freedesktop.login1.policy.in:279
+#: src/login/org.freedesktop.login1.policy:279
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
@@ -425,21 +425,21 @@ msgstr ""
"Authentification requise pour mettre le système en veille alors qu'une "
"application a demandé de l'empêcher."
-#: src/login/org.freedesktop.login1.policy.in:289
+#: src/login/org.freedesktop.login1.policy:289
msgid "Hibernate the system"
msgstr "Mettre le système en hibernation"
-#: src/login/org.freedesktop.login1.policy.in:290
+#: src/login/org.freedesktop.login1.policy:290
msgid "Authentication is required for hibernating the system."
msgstr "Authentification requise pour mettre le système en hibernation."
-#: src/login/org.freedesktop.login1.policy.in:299
+#: src/login/org.freedesktop.login1.policy:299
msgid "Hibernate the system while other users are logged in"
msgstr ""
"Mettre le système en hibernation alors que d'autres utilisateurs sont "
"connectés"
-#: src/login/org.freedesktop.login1.policy.in:300
+#: src/login/org.freedesktop.login1.policy:300
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
@@ -447,13 +447,13 @@ msgstr ""
"Authentification requise pour mettre le système en hibernation alors que "
"d'autres utilisateurs sont connectés."
-#: src/login/org.freedesktop.login1.policy.in:310
+#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while an application asked to inhibit it"
msgstr ""
"Mettre le système en hibernation alors qu'une application a demandé de "
"l'empêcher"
-#: src/login/org.freedesktop.login1.policy.in:311
+#: src/login/org.freedesktop.login1.policy:311
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
@@ -461,34 +461,34 @@ msgstr ""
"Authentification requise pour mettre le système en hibernation alors qu'une "
"application a demandé de l'empêcher."
-#: src/login/org.freedesktop.login1.policy.in:321
+#: src/login/org.freedesktop.login1.policy:321
msgid "Manage active sessions, users and seats"
msgstr "Gérer les sessions actives, les utilisateurs et les postes (seats)"
-#: src/login/org.freedesktop.login1.policy.in:322
+#: src/login/org.freedesktop.login1.policy:322
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
"Authentification requise pour gérer les sessions actives, les utilisateurs "
"et les postes (seats)."
-#: src/login/org.freedesktop.login1.policy.in:331
+#: src/login/org.freedesktop.login1.policy:331
msgid "Lock or unlock active sessions"
msgstr "Verrouiller ou déverrouiller des sessions actives"
-#: src/login/org.freedesktop.login1.policy.in:332
+#: src/login/org.freedesktop.login1.policy:332
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Authentification requise pour verrouiller ou déverrouiller des sessions "
"actives."
-#: src/login/org.freedesktop.login1.policy.in:341
+#: src/login/org.freedesktop.login1.policy:341
msgid "Allow indication to the firmware to boot to setup interface"
msgstr ""
"Permet d'indiquer au micrologiciel de démarrer sur l'interface de "
"configuration"
-#: src/login/org.freedesktop.login1.policy.in:342
+#: src/login/org.freedesktop.login1.policy:342
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
@@ -496,86 +496,86 @@ msgstr ""
"Authentification requise pour indiquer au micrologiciel de démarrer sur "
"l'interface de configuration."
-#: src/login/org.freedesktop.login1.policy.in:351
+#: src/login/org.freedesktop.login1.policy:351
msgid "Set a wall message"
msgstr "Définir un message wall"
-#: src/login/org.freedesktop.login1.policy.in:352
+#: src/login/org.freedesktop.login1.policy:352
msgid "Authentication is required to set a wall message"
msgstr "Authentification requise pour définir un message wall."
-#: src/machine/org.freedesktop.machine1.policy.in:22
+#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
msgstr "Connexion dans un conteneur local"
-#: src/machine/org.freedesktop.machine1.policy.in:23
+#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
msgstr ""
"Authentification requise pour permettre la connexion dans un conteneur local."
-#: src/machine/org.freedesktop.machine1.policy.in:32
+#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
msgstr "Connexion à l'hôte local"
-#: src/machine/org.freedesktop.machine1.policy.in:33
+#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
msgstr "Authentification requise pour permettre la connexion à l'hôte local."
-#: src/machine/org.freedesktop.machine1.policy.in:42
+#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
msgstr "Obtenir une interface système dans un conteneur local"
-#: src/machine/org.freedesktop.machine1.policy.in:43
+#: src/machine/org.freedesktop.machine1.policy:43
msgid "Authentication is required to acquire a shell in a local container."
msgstr ""
"Authentification requise pour obtenir une interface système dans un "
"conteneur local."
-#: src/machine/org.freedesktop.machine1.policy.in:53
+#: src/machine/org.freedesktop.machine1.policy:53
msgid "Acquire a shell on the local host"
msgstr "Obtenir une interface système sur l'hôte local"
-#: src/machine/org.freedesktop.machine1.policy.in:54
+#: src/machine/org.freedesktop.machine1.policy:54
msgid "Authentication is required to acquire a shell on the local host."
msgstr ""
"Authentification requise pour obtenir une interface système sur l'hôte local."
-#: src/machine/org.freedesktop.machine1.policy.in:64
+#: src/machine/org.freedesktop.machine1.policy:64
msgid "Acquire a pseudo TTY in a local container"
msgstr "Obtenir un pseudo terminal dans un conteneur local"
-#: src/machine/org.freedesktop.machine1.policy.in:65
+#: src/machine/org.freedesktop.machine1.policy:65
msgid ""
"Authentication is required to acquire a pseudo TTY in a local container."
msgstr ""
"Authentification requise pour obtenir un pseudo terminal dans un conteneur "
"local."
-#: src/machine/org.freedesktop.machine1.policy.in:74
+#: src/machine/org.freedesktop.machine1.policy:74
msgid "Acquire a pseudo TTY on the local host"
msgstr "Obtenir un pseudo terminal sur l'hôte local"
-#: src/machine/org.freedesktop.machine1.policy.in:75
+#: src/machine/org.freedesktop.machine1.policy:75
msgid "Authentication is required to acquire a pseudo TTY on the local host."
msgstr ""
"Authentification requise pour obtenir un pseudo terminal sur l'hôte local."
-#: src/machine/org.freedesktop.machine1.policy.in:84
+#: src/machine/org.freedesktop.machine1.policy:84
msgid "Manage local virtual machines and containers"
msgstr "Gérer les machines virtuelles (VM) et conteneurs locaux"
-#: src/machine/org.freedesktop.machine1.policy.in:85
+#: src/machine/org.freedesktop.machine1.policy:85
msgid ""
"Authentication is required to manage local virtual machines and containers."
msgstr ""
"Authentification requise pour gérer les machines virtuelles (VM) et les "
"conteneurs locaux."
-#: src/machine/org.freedesktop.machine1.policy.in:95
+#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
msgstr "Gérer les images locales de machines virtuelles (VM) et de conteneurs"
-#: src/machine/org.freedesktop.machine1.policy.in:96
+#: src/machine/org.freedesktop.machine1.policy:96
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
@@ -583,45 +583,75 @@ msgstr ""
"Authentification requise pour gérer les images locales de machines "
"virtuelles (VM) et de conteneurs."
-#: src/resolve/org.freedesktop.resolve1.policy.in:22
+#: src/portable/org.freedesktop.portable1.policy:13
+msgid "Inspect a portable service image"
+msgstr "Inspecter une image de service portable"
+
+#: src/portable/org.freedesktop.portable1.policy:14
+msgid "Authentication is required to inspect a portable service image."
+msgstr "Authentification requise pour inspecter une image de service portable."
+
+#: src/portable/org.freedesktop.portable1.policy:23
+msgid "Attach or detach a portable service image"
+msgstr "Attacher ou détacher une image de service portable"
+
+#: src/portable/org.freedesktop.portable1.policy:24
+msgid ""
+"Authentication is required to attach or detach a portable service image."
+msgstr ""
+"Authentification requise pour attacher ou détacher une image de service "
+"portable."
+
+#: src/portable/org.freedesktop.portable1.policy:34
+msgid "Delete or modify portable service image"
+msgstr "Supprimer ou modifier une image de service portable"
+
+#: src/portable/org.freedesktop.portable1.policy:35
+msgid ""
+"Authentication is required to delete or modify a portable service image."
+msgstr ""
+"Authentification requise pour supprimer ou modifier une image de service "
+"portable."
+
+#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
msgstr "Enregistrer un service DNS-SD"
-#: src/resolve/org.freedesktop.resolve1.policy.in:23
+#: src/resolve/org.freedesktop.resolve1.policy:23
msgid "Authentication is required to register a DNS-SD service"
msgstr "Authentification requise pour enregistrer un service DNS-SD"
-#: src/resolve/org.freedesktop.resolve1.policy.in:33
+#: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service"
msgstr "Retirer un service DNS-SD"
-#: src/resolve/org.freedesktop.resolve1.policy.in:34
+#: src/resolve/org.freedesktop.resolve1.policy:34
msgid "Authentication is required to unregister a DNS-SD service"
msgstr "Authentification requise pour retirer un service DNS-SD"
-#: src/timedate/org.freedesktop.timedate1.policy.in:22
+#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
msgstr "Définir l'heure du système"
-#: src/timedate/org.freedesktop.timedate1.policy.in:23
+#: src/timedate/org.freedesktop.timedate1.policy:23
msgid "Authentication is required to set the system time."
msgstr "Authentification requise pour définir l'heure du système."
-#: src/timedate/org.freedesktop.timedate1.policy.in:33
+#: src/timedate/org.freedesktop.timedate1.policy:33
msgid "Set system timezone"
msgstr "Définir le fuseau horaire du système"
-#: src/timedate/org.freedesktop.timedate1.policy.in:34
+#: src/timedate/org.freedesktop.timedate1.policy:34
msgid "Authentication is required to set the system timezone."
msgstr "Authentification requise pour définir le fuseau horaire du système."
-#: src/timedate/org.freedesktop.timedate1.policy.in:43
+#: src/timedate/org.freedesktop.timedate1.policy:43
msgid "Set RTC to local timezone or UTC"
msgstr ""
"Positionner l'horloge matérielle à l'heure locale ou sur le temps universel "
"coordonné (UTC)"
-#: src/timedate/org.freedesktop.timedate1.policy.in:44
+#: src/timedate/org.freedesktop.timedate1.policy:44
msgid ""
"Authentication is required to control whether the RTC stores the local or "
"UTC time."
@@ -629,11 +659,11 @@ msgstr ""
"Authentification requise pour positionner l'horloge matérielle à l'heure "
"locale ou sur le temps universel coordonné (UTC)."
-#: src/timedate/org.freedesktop.timedate1.policy.in:54
+#: src/timedate/org.freedesktop.timedate1.policy:53
msgid "Turn network time synchronization on or off"
msgstr "Activer ou désactiver la synchronisation de l'heure avec le réseau"
-#: src/timedate/org.freedesktop.timedate1.policy.in:55
+#: src/timedate/org.freedesktop.timedate1.policy:54
msgid ""
"Authentication is required to control whether network time synchronization "
"shall be enabled."
@@ -641,33 +671,33 @@ msgstr ""
"Authentification requise pour activer ou désactiver la synchronisation de "
"l'heure avec le réseau."
-#: src/core/dbus-unit.c:496
+#: src/core/dbus-unit.c:326
msgid "Authentication is required to start '$(unit)'."
msgstr "Authentification requise pour démarrer « $(unit) »."
-#: src/core/dbus-unit.c:497
+#: src/core/dbus-unit.c:327
msgid "Authentication is required to stop '$(unit)'."
msgstr "Authentification requise pour arrêter « $(unit) »."
-#: src/core/dbus-unit.c:498
+#: src/core/dbus-unit.c:328
msgid "Authentication is required to reload '$(unit)'."
msgstr "Authentification requise pour recharger « $(unit) »."
-#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500
+#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330
msgid "Authentication is required to restart '$(unit)'."
msgstr "Authentification requise pour redémarrer « $(unit) »."
-#: src/core/dbus-unit.c:607
+#: src/core/dbus-unit.c:437
msgid "Authentication is required to kill '$(unit)'."
msgstr "Authentification requise pour tuer « $(unit) »."
-#: src/core/dbus-unit.c:638
+#: src/core/dbus-unit.c:468
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr ""
"Authentification requise pour réinitialiser l'état d'« échec » de "
"« $(unit) »."
-#: src/core/dbus-unit.c:671
+#: src/core/dbus-unit.c:501
msgid "Authentication is required to set properties on '$(unit)'."
msgstr "Authentification requise pour définir des propriétés de « $(unit) »."
diff --git a/po/gl.po b/po/gl.po
index 92000f5956..bb7a6e678f 100644
--- a/po/gl.po
+++ b/po/gl.po
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# Copyright (C) 2015
# This file is distributed under the same license as the systemd package.
# Fran Dieguez <frandieguez@gnome.org>, 2015.
msgid ""
diff --git a/po/hr.po b/po/hr.po
index 2f282cdfca..4c884f18ab 100644
--- a/po/hr.po
+++ b/po/hr.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# gogo <trebelnik2@gmail.com>, 2016.
#
diff --git a/po/hu.po b/po/hu.po
index 77b7a00a69..2e4c411257 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Hungarian translation of systemd
-# Copyright (C) 2015, 2016. Free Software Foundation, Inc.
+# Copyright © 2015, 2016. Free Software Foundation, Inc.
# This file is distributed under the same license as the systemd package.
#
# Gabor Kelemen <kelemeng at gnome dot hu>, 2015, 2016.
diff --git a/po/id.po b/po/id.po
index 2803e134fc..a26fd9c9c2 100644
--- a/po/id.po
+++ b/po/id.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Indonesian translation for systemd.
-# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Andika Triwidada <andika@gmail.com>, 2014.
#
diff --git a/po/ja.po b/po/ja.po
index 7f0b81bf19..d0799b1255 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Japanese translation for systemd.
-# Copyright (C) 2018 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Yu Watanabe <watanabe.yu+github@gmail.com>, 2018.
#
@@ -10,7 +9,7 @@ msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
"POT-Creation-Date: 2018-02-27 16:46+0900\n"
-"PO-Revision-Date: 2018-02-27 16:55+0900\n"
+"PO-Revision-Date: 2018-05-28 10:30+0900\n"
"Last-Translator: Yu Watanabe <watanabe.yu+github@gmail.com>\n"
"Language-Team: \n"
"Language: ja\n"
@@ -25,8 +24,7 @@ msgstr "パスフレーズをシステムに送信"
#: src/core/org.freedesktop.systemd1.policy.in:23
msgid ""
"Authentication is required to send the entered passphrase back to the system."
-msgstr ""
-"パスフレーズをシステムに送信するには認証が必要です。"
+msgstr "パスフレーズをシステムに送信するには認証が必要です。"
#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
@@ -44,47 +42,47 @@ msgstr "システムサービスファイルやその他のユニットファイ
msgid "Authentication is required to manage system service or unit files."
msgstr "システムサービスファイルやその他のユニットファイルを管理するには認証が必要です。"
-#: src/core/org.freedesktop.systemd1.policy.in:53
+#: src/core/org.freedesktop.systemd1.policy.in:54
msgid "Set or unset system and service manager environment variables"
msgstr "システムマネージャ環境変数の設定もしくは解除"
-#: src/core/org.freedesktop.systemd1.policy.in:54
+#: src/core/org.freedesktop.systemd1.policy.in:55
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
msgstr "システムマネージャ環境変数を設定もしくは解除するには認証が必要です。"
-#: src/core/org.freedesktop.systemd1.policy.in:63
+#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Reload the systemd state"
msgstr "systemdの状態の再読込"
-#: src/core/org.freedesktop.systemd1.policy.in:64
+#: src/core/org.freedesktop.systemd1.policy.in:65
msgid "Authentication is required to reload the systemd state."
msgstr "systemdの状態を再読込するには認証が必要です。"
-#: src/hostname/org.freedesktop.hostname1.policy:22
+#: src/hostname/org.freedesktop.hostname1.policy:20
msgid "Set host name"
msgstr "ホスト名の設定"
-#: src/hostname/org.freedesktop.hostname1.policy:23
+#: src/hostname/org.freedesktop.hostname1.policy:21
msgid "Authentication is required to set the local host name."
msgstr "ホスト名を設定するには認証が必要です。"
-#: src/hostname/org.freedesktop.hostname1.policy:32
+#: src/hostname/org.freedesktop.hostname1.policy:30
msgid "Set static host name"
msgstr "静的なホスト名の設定"
-#: src/hostname/org.freedesktop.hostname1.policy:33
+#: src/hostname/org.freedesktop.hostname1.policy:31
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
msgstr "静的なホスト名を設定するには認証が必要です。"
-#: src/hostname/org.freedesktop.hostname1.policy:43
+#: src/hostname/org.freedesktop.hostname1.policy:41
msgid "Set machine information"
msgstr "マシン情報の設定"
-#: src/hostname/org.freedesktop.hostname1.policy:44
+#: src/hostname/org.freedesktop.hostname1.policy:42
msgid "Authentication is required to set local machine information."
msgstr "マシン情報を設定するには認証が必要です。"
@@ -487,6 +485,32 @@ msgid ""
"images."
msgstr "ローカルな仮想マシンやコンテナのイメージを管理するには認証が必要です。"
+#: src/portable/org.freedesktop.portable1.policy:13
+msgid "Inspect a portable service image"
+msgstr "ポータブルサービスイメージの読み込み"
+
+#: src/portable/org.freedesktop.portable1.policy:14
+msgid "Authentication is required to inspect a portable service image."
+msgstr "ポータブルサービスイメージを読み込むには認証が必要です。"
+
+#: src/portable/org.freedesktop.portable1.policy:23
+msgid "Attach or detach a portable service image"
+msgstr "ポータブルサービスイメージの接続もしくは切り離し"
+
+#: src/portable/org.freedesktop.portable1.policy:24
+msgid ""
+"Authentication is required to attach or detach a portable service image."
+msgstr "ポータブルサービスイメージを接続もしくは切り離すには認証が必要です。"
+
+#: src/portable/org.freedesktop.portable1.policy:34
+msgid "Delete or modify portable service image"
+msgstr "ポータブルサービスイメージの削除もしくは修正"
+
+#: src/portable/org.freedesktop.portable1.policy:35
+msgid ""
+"Authentication is required to delete or modify a portable service image."
+msgstr "ポータブルサービスイメージを削除もしくは修正するには認証が必要です。"
+
#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
msgstr "DNS-SDサービスを登録"
@@ -529,40 +553,40 @@ msgid ""
"UTC time."
msgstr "ハードウェア時刻をローカルタイムゾーンもしくはUTCに設定するには認証が必要です。"
-#: src/timedate/org.freedesktop.timedate1.policy:54
+#: src/timedate/org.freedesktop.timedate1.policy:53
msgid "Turn network time synchronization on or off"
msgstr "ネットワーク経由の時刻同期の有効化もしくは無効化"
-#: src/timedate/org.freedesktop.timedate1.policy:55
+#: src/timedate/org.freedesktop.timedate1.policy:54
msgid ""
"Authentication is required to control whether network time synchronization "
"shall be enabled."
msgstr "ネットワーク経由の時刻同期を有効もしくは無効にするには認証が必要です。"
-#: src/core/dbus-unit.c:496
+#: src/core/dbus-unit.c:326
msgid "Authentication is required to start '$(unit)'."
msgstr "'$(unit)'を開始するには認証が必要です。"
-#: src/core/dbus-unit.c:497
+#: src/core/dbus-unit.c:327
msgid "Authentication is required to stop '$(unit)'."
msgstr "'$(unit)'を停止するには認証が必要です。"
-#: src/core/dbus-unit.c:498
+#: src/core/dbus-unit.c:328
msgid "Authentication is required to reload '$(unit)'."
msgstr "'$(unit)'を再読込するには認証が必要です。"
-#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500
+#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330
msgid "Authentication is required to restart '$(unit)'."
msgstr "'$(unit)'を再起動するには認証が必要です。"
-#: src/core/dbus-unit.c:607
+#: src/core/dbus-unit.c:437
msgid "Authentication is required to kill '$(unit)'."
msgstr "'$(unit)'を強制停止するには認証が必要です。"
-#: src/core/dbus-unit.c:638
+#: src/core/dbus-unit.c:468
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr "'$(unit)'の「失敗」状態をリセットするには認証が必要です。"
-#: src/core/dbus-unit.c:671
+#: src/core/dbus-unit.c:501
msgid "Authentication is required to set properties on '$(unit)'."
msgstr "'$(unit)'のプロパティを設定するには認証が必要です。"
diff --git a/po/ko.po b/po/ko.po
index 7a1e9e1c68..f05083a69c 100644
--- a/po/ko.po
+++ b/po/ko.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Korean translation for the systemd.
-# Copyright (C) 2015 systemd author and translators.
# This file is distributed under the same license as the systemd package.
# Seong-ho Cho <shcho@gnome.org>, 2015.
# Dongsu Park <dongsu@endocode.com>, 2015.
diff --git a/po/meson.build b/po/meson.build
index 01ab7a3a54..3611ac90f1 100644
--- a/po/meson.build
+++ b/po/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
i18n = import('i18n')
i18n.gettext(meson.project_name(),
diff --git a/po/pl.po b/po/pl.po
index bb9f34537e..93dfbabfd9 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Polish translation for systemd.
-# Copyright © 2011-2018 the systemd authors.
# This file is distributed under the same license as the systemd package.
# Piotr Drąg <piotrdrag@gmail.com>, 2011, 2013-2018.
# Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>, 2011.
@@ -10,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2018-02-13 03:26+0000\n"
-"PO-Revision-Date: 2018-02-13 16:50+0100\n"
+"POT-Creation-Date: 2018-06-19 15:00+0000\n"
+"PO-Revision-Date: 2018-06-19 17:05+0200\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
"Language: pl\n"
@@ -21,43 +20,43 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
-#: src/core/org.freedesktop.systemd1.policy.in.in:22
+#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
msgstr "Wysłanie hasła z powrotem do systemu"
-#: src/core/org.freedesktop.systemd1.policy.in.in:23
+#: src/core/org.freedesktop.systemd1.policy.in:23
msgid ""
"Authentication is required to send the entered passphrase back to the system."
msgstr ""
"Wymagane jest uwierzytelnienie, aby wysłać podane hasło z powrotem do "
"systemu."
-#: src/core/org.freedesktop.systemd1.policy.in.in:33
+#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
msgstr "Zarządzanie usługami lub innymi jednostkami systemu"
-#: src/core/org.freedesktop.systemd1.policy.in.in:34
+#: src/core/org.freedesktop.systemd1.policy.in:34
msgid "Authentication is required to manage system services or other units."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zarządzać usługami lub innymi "
"jednostkami systemu."
-#: src/core/org.freedesktop.systemd1.policy.in.in:43
+#: src/core/org.freedesktop.systemd1.policy.in:43
msgid "Manage system service or unit files"
msgstr "Zarządzanie plikami usług lub jednostek systemu"
-#: src/core/org.freedesktop.systemd1.policy.in.in:44
+#: src/core/org.freedesktop.systemd1.policy.in:44
msgid "Authentication is required to manage system service or unit files."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zarządzać plikami usług lub jednostek "
"systemu."
-#: src/core/org.freedesktop.systemd1.policy.in.in:53
+#: src/core/org.freedesktop.systemd1.policy.in:54
msgid "Set or unset system and service manager environment variables"
msgstr ""
"Ustawienie lub usunięcie zmiennych środowiskowych menedżera systemu i usług"
-#: src/core/org.freedesktop.systemd1.policy.in.in:54
+#: src/core/org.freedesktop.systemd1.policy.in:55
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
@@ -65,27 +64,27 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby ustawić lub usunąć zmienne środowiskowe "
"menedżera systemu i usług."
-#: src/core/org.freedesktop.systemd1.policy.in.in:63
+#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Reload the systemd state"
msgstr "Ponowne wczytanie stanu systemd"
-#: src/core/org.freedesktop.systemd1.policy.in.in:64
+#: src/core/org.freedesktop.systemd1.policy.in:65
msgid "Authentication is required to reload the systemd state."
msgstr "Wymagane jest uwierzytelnienie, aby ponownie wczytać stan systemd."
-#: src/hostname/org.freedesktop.hostname1.policy.in:22
+#: src/hostname/org.freedesktop.hostname1.policy:20
msgid "Set host name"
msgstr "Ustawienie nazwy komputera"
-#: src/hostname/org.freedesktop.hostname1.policy.in:23
+#: src/hostname/org.freedesktop.hostname1.policy:21
msgid "Authentication is required to set the local host name."
msgstr "Wymagane jest uwierzytelnienie, aby ustawić nazwę lokalnego komputera."
-#: src/hostname/org.freedesktop.hostname1.policy.in:32
+#: src/hostname/org.freedesktop.hostname1.policy:30
msgid "Set static host name"
msgstr "Ustawienie statycznej nazwy komputera"
-#: src/hostname/org.freedesktop.hostname1.policy.in:33
+#: src/hostname/org.freedesktop.hostname1.policy:31
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
@@ -93,111 +92,111 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby ustawić statycznie skonfigurowaną nazwę "
"lokalnego komputera, a także jego nazwę czytelną dla człowieka."
-#: src/hostname/org.freedesktop.hostname1.policy.in:43
+#: src/hostname/org.freedesktop.hostname1.policy:41
msgid "Set machine information"
msgstr "Ustawienie informacji o komputerze"
-#: src/hostname/org.freedesktop.hostname1.policy.in:44
+#: src/hostname/org.freedesktop.hostname1.policy:42
msgid "Authentication is required to set local machine information."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ustawić informacje o lokalnym komputerze."
-#: src/import/org.freedesktop.import1.policy.in:22
+#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
msgstr "Import obrazu maszyny wirtualnej lub kontenera"
-#: src/import/org.freedesktop.import1.policy.in:23
+#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
msgstr ""
"Wymagane jest uwierzytelnienie, aby zaimportować obraz maszyny wirtualnej "
"lub kontenera"
-#: src/import/org.freedesktop.import1.policy.in:32
+#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
msgstr "Eksport obrazu maszyny wirtualnej lub kontenera"
-#: src/import/org.freedesktop.import1.policy.in:33
+#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
msgstr ""
"Wymagane jest uwierzytelnienie, aby wyeksportować obraz maszyny wirtualnej "
"lub kontenera"
-#: src/import/org.freedesktop.import1.policy.in:42
+#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
msgstr "Pobranie obrazu maszyny wirtualnej lub kontenera"
-#: src/import/org.freedesktop.import1.policy.in:43
+#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
msgstr ""
"Wymagane jest uwierzytelnienie, aby pobrać obraz maszyny wirtualnej lub "
"kontenera"
-#: src/locale/org.freedesktop.locale1.policy.in:22
+#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
msgstr "Ustawienie lokalizacji systemu"
-#: src/locale/org.freedesktop.locale1.policy.in:23
+#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
msgstr "Wymagane jest uwierzytelnienie, aby ustawić lokalizację systemu."
-#: src/locale/org.freedesktop.locale1.policy.in:33
+#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
msgstr "Ustawienie klawiatury systemu"
-#: src/locale/org.freedesktop.locale1.policy.in:34
+#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
msgstr "Wymagane jest uwierzytelnienie, aby ustawić klawiaturę systemu."
-#: src/login/org.freedesktop.login1.policy.in:22
+#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
msgstr "Zezwolenie programom na wstrzymywanie wyłączenia systemu"
-#: src/login/org.freedesktop.login1.policy.in:23
+#: src/login/org.freedesktop.login1.policy:23
msgid ""
"Authentication is required for an application to inhibit system shutdown."
msgstr "Program wymaga uwierzytelnienia, aby wstrzymać wyłączenie systemu."
-#: src/login/org.freedesktop.login1.policy.in:33
+#: src/login/org.freedesktop.login1.policy:33
msgid "Allow applications to delay system shutdown"
msgstr "Zezwolenie programom na opóźnienie wyłączenia systemu"
-#: src/login/org.freedesktop.login1.policy.in:34
+#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
msgstr "Program wymaga uwierzytelnienia, aby opóźnić wyłączenie systemu."
-#: src/login/org.freedesktop.login1.policy.in:44
+#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
msgstr "Zezwolenie programom na wstrzymanie uśpienia systemu"
-#: src/login/org.freedesktop.login1.policy.in:45
+#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr "Program wymaga uwierzytelnienia, aby wstrzymać uśpienie systemu."
-#: src/login/org.freedesktop.login1.policy.in:55
+#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"
msgstr "Zezwolenie programom na opóźnienie uśpienia systemu"
-#: src/login/org.freedesktop.login1.policy.in:56
+#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
msgstr "Program wymaga uwierzytelnienia, aby opóźnić uśpienie systemu."
-#: src/login/org.freedesktop.login1.policy.in:65
+#: src/login/org.freedesktop.login1.policy:65
msgid "Allow applications to inhibit automatic system suspend"
msgstr "Zezwolenie programom na wstrzymanie automatycznego uśpienia systemu"
-#: src/login/org.freedesktop.login1.policy.in:66
+#: src/login/org.freedesktop.login1.policy:66
msgid ""
"Authentication is required for an application to inhibit automatic system "
"suspend."
msgstr ""
"Program wymaga uwierzytelnienia, aby wstrzymać automatyczne uśpienie systemu."
-#: src/login/org.freedesktop.login1.policy.in:75
+#: src/login/org.freedesktop.login1.policy:75
msgid "Allow applications to inhibit system handling of the power key"
msgstr ""
"Zezwolenie programom na wstrzymanie obsługi klawisza zasilania przez system"
-#: src/login/org.freedesktop.login1.policy.in:76
+#: src/login/org.freedesktop.login1.policy:76
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the power key."
@@ -205,12 +204,12 @@ msgstr ""
"Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza zasilania "
"przez system."
-#: src/login/org.freedesktop.login1.policy.in:86
+#: src/login/org.freedesktop.login1.policy:86
msgid "Allow applications to inhibit system handling of the suspend key"
msgstr ""
"Zezwolenie programom na wstrzymanie obsługi klawisza uśpienia przez system"
-#: src/login/org.freedesktop.login1.policy.in:87
+#: src/login/org.freedesktop.login1.policy:87
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
@@ -218,12 +217,12 @@ msgstr ""
"Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza uśpienia "
"przez system."
-#: src/login/org.freedesktop.login1.policy.in:97
+#: src/login/org.freedesktop.login1.policy:97
msgid "Allow applications to inhibit system handling of the hibernate key"
msgstr ""
"Zezwolenie programom na wstrzymanie obsługi klawisza hibernacji przez system"
-#: src/login/org.freedesktop.login1.policy.in:98
+#: src/login/org.freedesktop.login1.policy:98
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
@@ -231,12 +230,12 @@ msgstr ""
"Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza hibernacji "
"przez system."
-#: src/login/org.freedesktop.login1.policy.in:107
+#: src/login/org.freedesktop.login1.policy:107
msgid "Allow applications to inhibit system handling of the lid switch"
msgstr ""
"Zezwolenie programom na wstrzymanie obsługi przełącznika pokrywy przez system"
-#: src/login/org.freedesktop.login1.policy.in:108
+#: src/login/org.freedesktop.login1.policy:108
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
@@ -244,59 +243,59 @@ msgstr ""
"Program wymaga uwierzytelnienia, aby wstrzymać obsługę przełącznika pokrywy "
"przez system."
-#: src/login/org.freedesktop.login1.policy.in:117
+#: src/login/org.freedesktop.login1.policy:117
msgid "Allow non-logged-in user to run programs"
msgstr "Zezwolenie niezalogowanemu użytkownikowi na uruchamianie programów"
-#: src/login/org.freedesktop.login1.policy.in:118
+#: src/login/org.freedesktop.login1.policy:118
msgid "Explicit request is required to run programs as a non-logged-in user."
msgstr ""
"Wymagane jest bezpośrednie żądanie, aby uruchamiać programy jako "
"niezalogowany użytkownik."
-#: src/login/org.freedesktop.login1.policy.in:127
+#: src/login/org.freedesktop.login1.policy:127
msgid "Allow non-logged-in users to run programs"
msgstr "Zezwolenie niezalogowanym użytkownikom na uruchamianie programów"
-#: src/login/org.freedesktop.login1.policy.in:128
+#: src/login/org.freedesktop.login1.policy:128
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
"Wymagane jest uwierzytelnienie, aby uruchamiać programy jako niezalogowany "
"użytkownik."
-#: src/login/org.freedesktop.login1.policy.in:137
+#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
msgstr "Zezwolenie na podłączanie urządzeń do stanowisk"
-#: src/login/org.freedesktop.login1.policy.in:138
+#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required for attaching a device to a seat."
msgstr ""
"Wymagane jest uwierzytelnienie, aby podłączyć urządzenie do stanowiska."
-#: src/login/org.freedesktop.login1.policy.in:148
+#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
msgstr "Usunięcie podłączenia urządzeń do stanowisk"
-#: src/login/org.freedesktop.login1.policy.in:149
+#: src/login/org.freedesktop.login1.policy:149
msgid ""
"Authentication is required for resetting how devices are attached to seats."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ponownie ustawić sposób podłączenia "
"urządzeń do stanowisk."
-#: src/login/org.freedesktop.login1.policy.in:158
+#: src/login/org.freedesktop.login1.policy:158
msgid "Power off the system"
msgstr "Wyłączenie systemu"
-#: src/login/org.freedesktop.login1.policy.in:159
+#: src/login/org.freedesktop.login1.policy:159
msgid "Authentication is required for powering off the system."
msgstr "Wymagane jest uwierzytelnienie, aby wyłączyć system."
-#: src/login/org.freedesktop.login1.policy.in:169
+#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system while other users are logged in"
msgstr "Wyłączenie systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy.in:170
+#: src/login/org.freedesktop.login1.policy:170
msgid ""
"Authentication is required for powering off the system while other users are "
"logged in."
@@ -304,11 +303,11 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy są zalogowani "
"inni użytkownicy."
-#: src/login/org.freedesktop.login1.policy.in:180
+#: src/login/org.freedesktop.login1.policy:180
msgid "Power off the system while an application asked to inhibit it"
msgstr "Wyłączenie systemu, kiedy program zażądał jego wstrzymania"
-#: src/login/org.freedesktop.login1.policy.in:181
+#: src/login/org.freedesktop.login1.policy:181
msgid ""
"Authentication is required for powering off the system while an application "
"asked to inhibit it."
@@ -316,19 +315,19 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy program zażądał "
"jego wstrzymania."
-#: src/login/org.freedesktop.login1.policy.in:191
+#: src/login/org.freedesktop.login1.policy:191
msgid "Reboot the system"
msgstr "Ponowne uruchomienie systemu"
-#: src/login/org.freedesktop.login1.policy.in:192
+#: src/login/org.freedesktop.login1.policy:192
msgid "Authentication is required for rebooting the system."
msgstr "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system."
-#: src/login/org.freedesktop.login1.policy.in:202
+#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system while other users are logged in"
msgstr "Ponowne uruchomienie systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy.in:203
+#: src/login/org.freedesktop.login1.policy:203
msgid ""
"Authentication is required for rebooting the system while other users are "
"logged in."
@@ -336,11 +335,11 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy są "
"zalogowani inni użytkownicy."
-#: src/login/org.freedesktop.login1.policy.in:213
+#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while an application asked to inhibit it"
msgstr "Ponowne uruchomienie systemu, kiedy program zażądał jego wstrzymania"
-#: src/login/org.freedesktop.login1.policy.in:214
+#: src/login/org.freedesktop.login1.policy:214
msgid ""
"Authentication is required for rebooting the system while an application "
"asked to inhibit it."
@@ -348,19 +347,19 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy program "
"zażądał jego wstrzymania."
-#: src/login/org.freedesktop.login1.policy.in:224
+#: src/login/org.freedesktop.login1.policy:224
msgid "Halt the system"
msgstr "Zatrzymanie systemu"
-#: src/login/org.freedesktop.login1.policy.in:225
+#: src/login/org.freedesktop.login1.policy:225
msgid "Authentication is required for halting the system."
msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać system."
-#: src/login/org.freedesktop.login1.policy.in:235
+#: src/login/org.freedesktop.login1.policy:235
msgid "Halt the system while other users are logged in"
msgstr "Zatrzymanie systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy.in:236
+#: src/login/org.freedesktop.login1.policy:236
msgid ""
"Authentication is required for halting the system while other users are "
"logged in."
@@ -368,11 +367,11 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby zatrzymać system, kiedy są zalogowani "
"inni użytkownicy."
-#: src/login/org.freedesktop.login1.policy.in:246
+#: src/login/org.freedesktop.login1.policy:246
msgid "Halt the system while an application asked to inhibit it"
msgstr "Zatrzymanie systemu, kiedy program zażądał jego wstrzymania"
-#: src/login/org.freedesktop.login1.policy.in:247
+#: src/login/org.freedesktop.login1.policy:247
msgid ""
"Authentication is required for halting the system while an application asked "
"to inhibit it."
@@ -380,19 +379,19 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby zatrzymać system, kiedy program zażądał "
"jego wstrzymania."
-#: src/login/org.freedesktop.login1.policy.in:257
+#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
msgstr "Uśpienie systemu"
-#: src/login/org.freedesktop.login1.policy.in:258
+#: src/login/org.freedesktop.login1.policy:258
msgid "Authentication is required for suspending the system."
msgstr "Wymagane jest uwierzytelnienie, aby uśpić system."
-#: src/login/org.freedesktop.login1.policy.in:267
+#: src/login/org.freedesktop.login1.policy:267
msgid "Suspend the system while other users are logged in"
msgstr "Uśpienie systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy.in:268
+#: src/login/org.freedesktop.login1.policy:268
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
@@ -400,11 +399,11 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby uśpić system, kiedy są zalogowani inni "
"użytkownicy."
-#: src/login/org.freedesktop.login1.policy.in:278
+#: src/login/org.freedesktop.login1.policy:278
msgid "Suspend the system while an application asked to inhibit it"
msgstr "Uśpienie systemu, kiedy program zażądał jego wstrzymania"
-#: src/login/org.freedesktop.login1.policy.in:279
+#: src/login/org.freedesktop.login1.policy:279
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
@@ -412,19 +411,19 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby uśpić system, kiedy program zażądał jego "
"wstrzymania."
-#: src/login/org.freedesktop.login1.policy.in:289
+#: src/login/org.freedesktop.login1.policy:289
msgid "Hibernate the system"
msgstr "Hibernacja systemu"
-#: src/login/org.freedesktop.login1.policy.in:290
+#: src/login/org.freedesktop.login1.policy:290
msgid "Authentication is required for hibernating the system."
msgstr "Wymagane jest uwierzytelnienie, aby zahibernować system."
-#: src/login/org.freedesktop.login1.policy.in:299
+#: src/login/org.freedesktop.login1.policy:299
msgid "Hibernate the system while other users are logged in"
msgstr "Hibernacja systemu, kiedy są zalogowani inni użytkownicy"
-#: src/login/org.freedesktop.login1.policy.in:300
+#: src/login/org.freedesktop.login1.policy:300
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
@@ -432,11 +431,11 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy są zalogowani "
"inni użytkownicy."
-#: src/login/org.freedesktop.login1.policy.in:310
+#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while an application asked to inhibit it"
msgstr "Hibernacja systemu, kiedy program zażądał jej wstrzymania"
-#: src/login/org.freedesktop.login1.policy.in:311
+#: src/login/org.freedesktop.login1.policy:311
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
@@ -444,31 +443,31 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy program "
"zażądał jej wstrzymania."
-#: src/login/org.freedesktop.login1.policy.in:321
+#: src/login/org.freedesktop.login1.policy:321
msgid "Manage active sessions, users and seats"
msgstr "Zarządzanie aktywnymi sesjami, użytkownikami i stanowiskami"
-#: src/login/org.freedesktop.login1.policy.in:322
+#: src/login/org.freedesktop.login1.policy:322
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zarządzać aktywnymi sesjami, "
"użytkownikami i stanowiskami."
-#: src/login/org.freedesktop.login1.policy.in:331
+#: src/login/org.freedesktop.login1.policy:331
msgid "Lock or unlock active sessions"
msgstr "Zablokowanie lub odblokowanie aktywnych sesji"
-#: src/login/org.freedesktop.login1.policy.in:332
+#: src/login/org.freedesktop.login1.policy:332
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zablokować lub odblokować aktywne sesje."
-#: src/login/org.freedesktop.login1.policy.in:341
+#: src/login/org.freedesktop.login1.policy:341
msgid "Allow indication to the firmware to boot to setup interface"
msgstr "Wskazanie oprogramowaniu sprzętowemu, aby uruchomić interfejs ustawień"
-#: src/login/org.freedesktop.login1.policy.in:342
+#: src/login/org.freedesktop.login1.policy:342
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
@@ -476,86 +475,86 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby wskazać oprogramowaniu sprzętowemu, że "
"należy uruchomić interfejs ustawień."
-#: src/login/org.freedesktop.login1.policy.in:351
+#: src/login/org.freedesktop.login1.policy:351
msgid "Set a wall message"
msgstr "Ustawienie komunikatu wall"
-#: src/login/org.freedesktop.login1.policy.in:352
+#: src/login/org.freedesktop.login1.policy:352
msgid "Authentication is required to set a wall message"
msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
-#: src/machine/org.freedesktop.machine1.policy.in:22
+#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
msgstr "Logowanie do lokalnego kontenera"
-#: src/machine/org.freedesktop.machine1.policy.in:23
+#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego kontenera."
-#: src/machine/org.freedesktop.machine1.policy.in:32
+#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
msgstr "Logowanie do lokalnego komputera"
-#: src/machine/org.freedesktop.machine1.policy.in:33
+#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego komputera."
-#: src/machine/org.freedesktop.machine1.policy.in:42
+#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
msgstr "Uzyskanie powłoki w lokalnym kontenerze"
-#: src/machine/org.freedesktop.machine1.policy.in:43
+#: src/machine/org.freedesktop.machine1.policy:43
msgid "Authentication is required to acquire a shell in a local container."
msgstr ""
"Wymagane jest uwierzytelnienie, aby uzyskać powłokę w lokalnym kontenerze."
-#: src/machine/org.freedesktop.machine1.policy.in:53
+#: src/machine/org.freedesktop.machine1.policy:53
msgid "Acquire a shell on the local host"
msgstr "Uzyskanie powłoki na lokalnym komputerze"
-#: src/machine/org.freedesktop.machine1.policy.in:54
+#: src/machine/org.freedesktop.machine1.policy:54
msgid "Authentication is required to acquire a shell on the local host."
msgstr ""
"Wymagane jest uwierzytelnienie, aby uzyskać powłokę na lokalnym komputerze."
-#: src/machine/org.freedesktop.machine1.policy.in:64
+#: src/machine/org.freedesktop.machine1.policy:64
msgid "Acquire a pseudo TTY in a local container"
msgstr "Uzyskanie pseudo-TTY w lokalnym kontenerze"
-#: src/machine/org.freedesktop.machine1.policy.in:65
+#: src/machine/org.freedesktop.machine1.policy:65
msgid ""
"Authentication is required to acquire a pseudo TTY in a local container."
msgstr ""
"Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY w lokalnym kontenerze."
-#: src/machine/org.freedesktop.machine1.policy.in:74
+#: src/machine/org.freedesktop.machine1.policy:74
msgid "Acquire a pseudo TTY on the local host"
msgstr "Uzyskanie pseudo-TTY na lokalnym komputerze"
-#: src/machine/org.freedesktop.machine1.policy.in:75
+#: src/machine/org.freedesktop.machine1.policy:75
msgid "Authentication is required to acquire a pseudo TTY on the local host."
msgstr ""
"Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY na lokalnym "
"komputerze."
-#: src/machine/org.freedesktop.machine1.policy.in:84
+#: src/machine/org.freedesktop.machine1.policy:84
msgid "Manage local virtual machines and containers"
msgstr "Zarządzanie lokalnymi maszynami wirtualnymi i kontenerami"
-#: src/machine/org.freedesktop.machine1.policy.in:85
+#: src/machine/org.freedesktop.machine1.policy:85
msgid ""
"Authentication is required to manage local virtual machines and containers."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi maszynami "
"wirtualnymi i kontenerami."
-#: src/machine/org.freedesktop.machine1.policy.in:95
+#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
msgstr "Zarządzanie lokalnymi obrazami maszyn wirtualnych i kontenerów"
-#: src/machine/org.freedesktop.machine1.policy.in:96
+#: src/machine/org.freedesktop.machine1.policy:96
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
@@ -563,43 +562,73 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi obrazami maszyn "
"wirtualnych i kontenerów."
-#: src/resolve/org.freedesktop.resolve1.policy.in:22
+#: src/portable/org.freedesktop.portable1.policy:13
+msgid "Inspect a portable service image"
+msgstr "Badanie obrazu przenośnej usługi"
+
+#: src/portable/org.freedesktop.portable1.policy:14
+msgid "Authentication is required to inspect a portable service image."
+msgstr "Wymagane jest uwierzytelnienie, aby zbadać obraz przenośnej usługi."
+
+#: src/portable/org.freedesktop.portable1.policy:23
+msgid "Attach or detach a portable service image"
+msgstr "Podłączenie lub odłączenie obrazu przenośnej usługi"
+
+#: src/portable/org.freedesktop.portable1.policy:24
+msgid ""
+"Authentication is required to attach or detach a portable service image."
+msgstr ""
+"Wymagane jest uwierzytelnienie, aby podłączyć lub odłączyć obraz przenośnej "
+"usługi."
+
+#: src/portable/org.freedesktop.portable1.policy:34
+msgid "Delete or modify portable service image"
+msgstr "Usunięcie lub modyfikacja obrazu przenośnej usługi"
+
+#: src/portable/org.freedesktop.portable1.policy:35
+msgid ""
+"Authentication is required to delete or modify a portable service image."
+msgstr ""
+"Wymagane jest uwierzytelnienie, aby usunąć lub zmodyfikować obraz przenośnej "
+"usługi."
+
+#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
msgstr "Rejestracja usługi DNS-SD"
-#: src/resolve/org.freedesktop.resolve1.policy.in:23
+#: src/resolve/org.freedesktop.resolve1.policy:23
msgid "Authentication is required to register a DNS-SD service"
msgstr "Wymagane jest uwierzytelnienie, aby zarejestrować usługę DNS-SD"
-#: src/resolve/org.freedesktop.resolve1.policy.in:33
+#: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service"
msgstr "Wyrejestrowanie usługi DNS-SD"
-#: src/resolve/org.freedesktop.resolve1.policy.in:34
+#: src/resolve/org.freedesktop.resolve1.policy:34
msgid "Authentication is required to unregister a DNS-SD service"
msgstr "Wymagane jest uwierzytelnienie, aby wyrejestrować usługę DNS-SD"
-#: src/timedate/org.freedesktop.timedate1.policy.in:22
+#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
msgstr "Ustawienie czasu systemu"
-#: src/timedate/org.freedesktop.timedate1.policy.in:23
+#: src/timedate/org.freedesktop.timedate1.policy:23
msgid "Authentication is required to set the system time."
msgstr "Wymagane jest uwierzytelnienie, aby ustawić czas systemu."
-#: src/timedate/org.freedesktop.timedate1.policy.in:33
+#: src/timedate/org.freedesktop.timedate1.policy:33
msgid "Set system timezone"
msgstr "Ustawienie strefy czasowej systemu"
-#: src/timedate/org.freedesktop.timedate1.policy.in:34
+#: src/timedate/org.freedesktop.timedate1.policy:34
msgid "Authentication is required to set the system timezone."
msgstr "Wymagane jest uwierzytelnienie, aby ustawić strefę czasową systemu."
-#: src/timedate/org.freedesktop.timedate1.policy.in:43
+#: src/timedate/org.freedesktop.timedate1.policy:43
msgid "Set RTC to local timezone or UTC"
msgstr "Ustawienie RTC na lokalną strefę czasową lub strefę UTC"
-#: src/timedate/org.freedesktop.timedate1.policy.in:44
+#: src/timedate/org.freedesktop.timedate1.policy:44
msgid ""
"Authentication is required to control whether the RTC stores the local or "
"UTC time."
@@ -607,11 +636,11 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby kontrolować, czy RTC przechowuje czas "
"lokalny lub czas UTC."
-#: src/timedate/org.freedesktop.timedate1.policy.in:54
+#: src/timedate/org.freedesktop.timedate1.policy:53
msgid "Turn network time synchronization on or off"
msgstr "Włączenie lub wyłączenie synchronizacji czasu przez sieć"
-#: src/timedate/org.freedesktop.timedate1.policy.in:55
+#: src/timedate/org.freedesktop.timedate1.policy:54
msgid ""
"Authentication is required to control whether network time synchronization "
"shall be enabled."
@@ -619,36 +648,36 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację "
"czasu przez sieć."
-#: src/core/dbus-unit.c:496
+#: src/core/dbus-unit.c:326
msgid "Authentication is required to start '$(unit)'."
msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”."
-#: src/core/dbus-unit.c:497
+#: src/core/dbus-unit.c:327
msgid "Authentication is required to stop '$(unit)'."
msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”."
-#: src/core/dbus-unit.c:498
+#: src/core/dbus-unit.c:328
msgid "Authentication is required to reload '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”."
-#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500
+#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330
msgid "Authentication is required to restart '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”."
-#: src/core/dbus-unit.c:607
+#: src/core/dbus-unit.c:437
msgid "Authentication is required to kill '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby wymusić wyłączenie jednostki „$(unit)”."
-#: src/core/dbus-unit.c:638
+#: src/core/dbus-unit.c:468
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby przywrócić stan „failed” (niepowodzenia) "
"jednostki „$(unit)”."
-#: src/core/dbus-unit.c:671
+#: src/core/dbus-unit.c:501
msgid "Authentication is required to set properties on '$(unit)'."
msgstr ""
"Wymagane jest uwierzytelnienie, aby ustawić właściwości jednostki „$(unit)”."
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 284ebca937..c288a26bba 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Brazilian Portuguese translation for systemd.
-# Copyright (C) 2017 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Enrico Nicoletto <liverig@gmail.com>, 2014.
# Rafael Fontenelle <rafaelff@gnome.org>, 2015, 2017.
diff --git a/po/ro.po b/po/ro.po
index d9109fc040..a4d7a5a4a0 100644
--- a/po/ro.po
+++ b/po/ro.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Romanian translation for systemd.
-# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# va511e <va511e@yahoo.com>, 2015.
# Daniel Șerbănescu <daniel [at] serbanescu [dot] dk>, 2015, 2017.
diff --git a/po/ru.po b/po/ru.po
index d75bb8fc08..826952b2c8 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -9,7 +9,7 @@ msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
"POT-Creation-Date: 2015-11-22 16:37+0100\n"
-"PO-Revision-Date: 2018-02-22 13:25+0300\n"
+"PO-Revision-Date: 2018-06-16 00:07+0300\n"
"Last-Translator: Sergey Ptashnick <0comffdiz@inbox.ru>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
@@ -18,40 +18,40 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
-#: src/core/org.freedesktop.systemd1.policy.in.in:22
+#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
msgstr "Отправить пароль системе"
-#: src/core/org.freedesktop.systemd1.policy.in.in:23
+#: src/core/org.freedesktop.systemd1.policy.in:23
msgid ""
"Authentication is required to send the entered passphrase back to the system."
msgstr "Чтобы отправить пароль системе, необходимо пройти аутентификацию."
-#: src/core/org.freedesktop.systemd1.policy.in.in:33
+#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
msgstr "Управление системными службами и юнитами"
-#: src/core/org.freedesktop.systemd1.policy.in.in:34
+#: src/core/org.freedesktop.systemd1.policy.in:34
msgid "Authentication is required to manage system services or other units."
msgstr ""
"Для управления системными службами и юнитами, необходимо пройти "
"аутентификацию."
-#: src/core/org.freedesktop.systemd1.policy.in.in:43
+#: src/core/org.freedesktop.systemd1.policy.in:43
msgid "Manage system service or unit files"
msgstr "Управление файлами конфигурации системных служб и юнитов"
-#: src/core/org.freedesktop.systemd1.policy.in.in:44
+#: src/core/org.freedesktop.systemd1.policy.in:44
msgid "Authentication is required to manage system service or unit files."
msgstr ""
"Для управления файлами конфигурации системных служб и юнитов, необходимо "
"пройти аутентификацию."
-#: src/core/org.freedesktop.systemd1.policy.in.in:53
+#: src/core/org.freedesktop.systemd1.policy.in:54
msgid "Set or unset system and service manager environment variables"
msgstr "Настроить переменные окружения для системного менеджера"
-#: src/core/org.freedesktop.systemd1.policy.in.in:54
+#: src/core/org.freedesktop.systemd1.policy.in:55
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
@@ -59,29 +59,29 @@ msgstr ""
"Чтобы настроить переменные окружения для системного менеджера, необходимо "
"пройти аутентификацию."
-#: src/core/org.freedesktop.systemd1.policy.in.in:63
+#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Reload the systemd state"
msgstr "Перечитать конфигурацию systemd"
-#: src/core/org.freedesktop.systemd1.policy.in.in:64
+#: src/core/org.freedesktop.systemd1.policy.in:65
msgid "Authentication is required to reload the systemd state."
msgstr ""
"Чтобы заставить systemd перечитать конфигурацию, необходимо пройти "
"аутентификацию."
-#: src/hostname/org.freedesktop.hostname1.policy.in:22
+#: src/hostname/org.freedesktop.hostname1.policy:22
msgid "Set host name"
msgstr "Настроить имя компьютера"
-#: src/hostname/org.freedesktop.hostname1.policy.in:23
+#: src/hostname/org.freedesktop.hostname1.policy:23
msgid "Authentication is required to set the local host name."
msgstr "Чтобы настроить имя компьютера, необходимо пройти аутентификацию."
-#: src/hostname/org.freedesktop.hostname1.policy.in:32
+#: src/hostname/org.freedesktop.hostname1.policy:32
msgid "Set static host name"
msgstr "Настроить статическое имя компьютера"
-#: src/hostname/org.freedesktop.hostname1.policy.in:33
+#: src/hostname/org.freedesktop.hostname1.policy:33
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
@@ -89,110 +89,110 @@ msgstr ""
"Чтобы настроить статическое имя компьютера, а также его «красивое» имя, "
"необходимо пройти аутентификацию."
-#: src/hostname/org.freedesktop.hostname1.policy.in:43
+#: src/hostname/org.freedesktop.hostname1.policy:43
msgid "Set machine information"
msgstr "Настроить информацию о компьютере"
-#: src/hostname/org.freedesktop.hostname1.policy.in:44
+#: src/hostname/org.freedesktop.hostname1.policy:44
msgid "Authentication is required to set local machine information."
msgstr ""
"Чтобы настроить информацию о компьютере, необходимо пройти аутентификацию."
-#: src/import/org.freedesktop.import1.policy.in:22
+#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
msgstr "Импортировать образ виртуальной машины или контейнера"
-#: src/import/org.freedesktop.import1.policy.in:23
+#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
msgstr ""
"Чтобы импортировать образ виртуальной машины или контейнера, необходимо "
"пройти аутентификацию."
-#: src/import/org.freedesktop.import1.policy.in:32
+#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
msgstr "Экспортировать образ виртуальной машины или контейнера"
-#: src/import/org.freedesktop.import1.policy.in:33
+#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
msgstr ""
"Чтобы экспортировать образ виртуальной машины или контейнера, необходимо "
"пройти аутентификацию."
-#: src/import/org.freedesktop.import1.policy.in:42
+#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
msgstr "Загрузить образ виртуальной машины или контейнера"
-#: src/import/org.freedesktop.import1.policy.in:43
+#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
msgstr ""
"Чтобы загрузить образ виртуальной машины или контейнера, необходимо пройти "
"аутентификацию."
-#: src/locale/org.freedesktop.locale1.policy.in:22
+#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
msgstr "Настроить системную локаль"
-#: src/locale/org.freedesktop.locale1.policy.in:23
+#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
msgstr "Чтобы настроить системную локаль, необходимо пройти аутентификацию."
-#: src/locale/org.freedesktop.locale1.policy.in:33
+#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
msgstr "Настроить параметры клавиатуры"
-#: src/locale/org.freedesktop.locale1.policy.in:34
+#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
msgstr ""
"Чтобы настроить параметры клавиатуры, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:22
+#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
msgstr "Разрешить приложениям устанавливать блокировку на выключение системы"
-#: src/login/org.freedesktop.login1.policy.in:23
+#: src/login/org.freedesktop.login1.policy:23
msgid ""
"Authentication is required for an application to inhibit system shutdown."
msgstr ""
"Чтобы разрешить приложениям устанавливать блокировку на выключение системы, "
"необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:33
+#: src/login/org.freedesktop.login1.policy:33
msgid "Allow applications to delay system shutdown"
msgstr "Разрешить приложениям устанавливать задержку на выключение системы"
-#: src/login/org.freedesktop.login1.policy.in:34
+#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
msgstr ""
"Чтобы разрешить приложениям устанавливать задержку на выключение системы, "
"необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:44
+#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
msgstr "Разрешить приложениям устанавливать блокировку на засыпание системы"
-#: src/login/org.freedesktop.login1.policy.in:45
+#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr ""
"Чтобы разрешить приложениям устанавливать блокировку на засыпание системы, "
"необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:55
+#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"
msgstr "Разрешить приложениям устанавливать задержку на засыпание системы"
-#: src/login/org.freedesktop.login1.policy.in:56
+#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
msgstr ""
"Чтобы разрешить приложениям устанавливать задержку на засыпание системы, "
"необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:65
+#: src/login/org.freedesktop.login1.policy:65
msgid "Allow applications to inhibit automatic system suspend"
msgstr ""
"Разрешить приложениям устанавливать блокировку на автоматический переход "
"системы в ждущий режим"
-#: src/login/org.freedesktop.login1.policy.in:66
+#: src/login/org.freedesktop.login1.policy:66
msgid ""
"Authentication is required for an application to inhibit automatic system "
"suspend."
@@ -200,13 +200,13 @@ msgstr ""
"Чтобы разрешить приложениям устанавливать блокировку на автоматический "
"переход системы в ждущий режим, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:75
+#: src/login/org.freedesktop.login1.policy:75
msgid "Allow applications to inhibit system handling of the power key"
msgstr ""
"Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку "
"выключения"
-#: src/login/org.freedesktop.login1.policy.in:76
+#: src/login/org.freedesktop.login1.policy:76
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the power key."
@@ -214,13 +214,13 @@ msgstr ""
"Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на "
"кнопку выключения, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:86
+#: src/login/org.freedesktop.login1.policy:86
msgid "Allow applications to inhibit system handling of the suspend key"
msgstr ""
"Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку "
"перехода в ждущий режим"
-#: src/login/org.freedesktop.login1.policy.in:87
+#: src/login/org.freedesktop.login1.policy:87
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
@@ -228,13 +228,13 @@ msgstr ""
"Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на "
"кнопку перехода в ждущий режим, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:97
+#: src/login/org.freedesktop.login1.policy:97
msgid "Allow applications to inhibit system handling of the hibernate key"
msgstr ""
"Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку "
"перехода в спящий режим"
-#: src/login/org.freedesktop.login1.policy.in:98
+#: src/login/org.freedesktop.login1.policy:98
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
@@ -242,13 +242,13 @@ msgstr ""
"Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на "
"кнопку перехода в спящий режим, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:107
+#: src/login/org.freedesktop.login1.policy:107
msgid "Allow applications to inhibit system handling of the lid switch"
msgstr ""
"Разрешить приложениям устанавливать блокировку на обработку закрытия крышки "
"ноутбука"
-#: src/login/org.freedesktop.login1.policy.in:108
+#: src/login/org.freedesktop.login1.policy:108
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
@@ -256,64 +256,64 @@ msgstr ""
"Чтобы разрешить приложениям устанавливать блокировку на обработку закрытия "
"крышки ноутбука, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:117
+#: src/login/org.freedesktop.login1.policy:117
msgid "Allow non-logged-in user to run programs"
msgstr ""
"Разрешить работу программ в фоновом режиме после завершения сеанса"
-#: src/login/org.freedesktop.login1.policy.in:118
+#: src/login/org.freedesktop.login1.policy:118
msgid "Explicit request is required to run programs as a non-logged-in user."
msgstr ""
"Чтобы разрешить работу программ в фоновом режиме после завершения сеанса, "
"необходимо явное подтверждение."
-#: src/login/org.freedesktop.login1.policy.in:127
+#: src/login/org.freedesktop.login1.policy:127
msgid "Allow non-logged-in users to run programs"
msgstr ""
"Разрешить пользователям оставлять программы в фоновом режиме после "
"завершения сеанса"
-#: src/login/org.freedesktop.login1.policy.in:128
+#: src/login/org.freedesktop.login1.policy:128
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
"Чтобы разрешить пользователям оставлять программы в фоновом режиме после "
"завершения сеанса, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:137
+#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
msgstr "Разрешить подключение устройств к рабочим местам"
-#: src/login/org.freedesktop.login1.policy.in:138
+#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required for attaching a device to a seat."
msgstr ""
"Чтобы разрешить подключение устройств к рабочим местам, необходимо пройти "
"аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:148
+#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
msgstr "Сбросить привязки устройств к рабочим местам"
-#: src/login/org.freedesktop.login1.policy.in:149
+#: src/login/org.freedesktop.login1.policy:149
msgid ""
"Authentication is required for resetting how devices are attached to seats."
msgstr ""
"Чтобы сбросить привязки устройств к рабочим местам, необходимо пройти "
"аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:158
+#: src/login/org.freedesktop.login1.policy:158
msgid "Power off the system"
msgstr "Выключить систему"
-#: src/login/org.freedesktop.login1.policy.in:159
+#: src/login/org.freedesktop.login1.policy:159
msgid "Authentication is required for powering off the system."
msgstr "Чтобы выключить систему, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:169
+#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system while other users are logged in"
msgstr ""
"Выключить систему, несмотря на то, что в ней работают другие пользователи"
-#: src/login/org.freedesktop.login1.policy.in:170
+#: src/login/org.freedesktop.login1.policy:170
msgid ""
"Authentication is required for powering off the system while other users are "
"logged in."
@@ -321,13 +321,13 @@ msgstr ""
"Чтобы выключить систему, несмотря на то, что в ней работают другие "
"пользователи, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:180
+#: src/login/org.freedesktop.login1.policy:180
msgid "Power off the system while an application asked to inhibit it"
msgstr ""
"Выключить систему, несмотря на то, что приложение запросило блокировку "
"выключения"
-#: src/login/org.freedesktop.login1.policy.in:181
+#: src/login/org.freedesktop.login1.policy:181
msgid ""
"Authentication is required for powering off the system while an application "
"asked to inhibit it."
@@ -335,20 +335,20 @@ msgstr ""
"Чтобы выключить систему, несмотря на то, что приложение запросило блокировку "
"выключения, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:191
+#: src/login/org.freedesktop.login1.policy:191
msgid "Reboot the system"
msgstr "Перезагрузить систему"
-#: src/login/org.freedesktop.login1.policy.in:192
+#: src/login/org.freedesktop.login1.policy:192
msgid "Authentication is required for rebooting the system."
msgstr "Чтобы перезагрузить систему, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:202
+#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system while other users are logged in"
msgstr ""
"Перезагрузить систему, несмотря на то, что в ней работают другие пользователи"
-#: src/login/org.freedesktop.login1.policy.in:203
+#: src/login/org.freedesktop.login1.policy:203
msgid ""
"Authentication is required for rebooting the system while other users are "
"logged in."
@@ -356,13 +356,13 @@ msgstr ""
"Чтобы перезагрузить систему, несмотря на то, что в ней работают другие "
"пользователи, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:213
+#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while an application asked to inhibit it"
msgstr ""
"Перезагрузить систему, несмотря на то, что приложение запросило блокировку "
"выключения"
-#: src/login/org.freedesktop.login1.policy.in:214
+#: src/login/org.freedesktop.login1.policy:214
msgid ""
"Authentication is required for rebooting the system while an application "
"asked to inhibit it."
@@ -370,20 +370,20 @@ msgstr ""
"Чтобы перезагрузить систему, несмотря на то, что приложение запросило "
"блокировку выключения, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:224
+#: src/login/org.freedesktop.login1.policy:224
msgid "Halt the system"
msgstr "Остановить систему"
-#: src/login/org.freedesktop.login1.policy.in:225
+#: src/login/org.freedesktop.login1.policy:225
msgid "Authentication is required for halting the system."
msgstr "Чтобы остановить систему, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:235
+#: src/login/org.freedesktop.login1.policy:235
msgid "Halt the system while other users are logged in"
msgstr ""
"Остановить систему, несмотря на то, что в ней работают другие пользователи"
-#: src/login/org.freedesktop.login1.policy.in:236
+#: src/login/org.freedesktop.login1.policy:236
msgid ""
"Authentication is required for halting the system while other users are "
"logged in."
@@ -391,13 +391,13 @@ msgstr ""
"Чтобы остановить систему, несмотря на то, что в ней работают другие "
"пользователи, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:246
+#: src/login/org.freedesktop.login1.policy:246
msgid "Halt the system while an application asked to inhibit it"
msgstr ""
"Остановить систему, несмотря на то, что приложение запросило блокировку "
"выключения"
-#: src/login/org.freedesktop.login1.policy.in:247
+#: src/login/org.freedesktop.login1.policy:247
msgid ""
"Authentication is required for halting the system while an application asked "
"to inhibit it."
@@ -405,22 +405,22 @@ msgstr ""
"Чтобы остановить систему, несмотря на то, что приложение запросило "
"блокировку выключения, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:257
+#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
msgstr "Перевести систему в ждущий режим"
-#: src/login/org.freedesktop.login1.policy.in:258
+#: src/login/org.freedesktop.login1.policy:258
msgid "Authentication is required for suspending the system."
msgstr ""
"Чтобы перевести систему в ждущий режим, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:267
+#: src/login/org.freedesktop.login1.policy:267
msgid "Suspend the system while other users are logged in"
msgstr ""
"Перевести систему в ждущий режим, несмотря на то, что в ней работают другие "
"пользователи"
-#: src/login/org.freedesktop.login1.policy.in:268
+#: src/login/org.freedesktop.login1.policy:268
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
@@ -428,13 +428,13 @@ msgstr ""
"Чтобы перевести систему в ждущий режим, несмотря на то, что в ней работают "
"другие пользователи, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:278
+#: src/login/org.freedesktop.login1.policy:278
msgid "Suspend the system while an application asked to inhibit it"
msgstr ""
"Перевести систему в ждущий режим, несмотря на то, что приложение запросило "
"блокировку"
-#: src/login/org.freedesktop.login1.policy.in:279
+#: src/login/org.freedesktop.login1.policy:279
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
@@ -442,22 +442,22 @@ msgstr ""
"Чтобы перевести систему в ждущий режим, несмотря на то, что приложение "
"запросило блокировку, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:289
+#: src/login/org.freedesktop.login1.policy:289
msgid "Hibernate the system"
msgstr "Перевести систему в спящий режим"
-#: src/login/org.freedesktop.login1.policy.in:290
+#: src/login/org.freedesktop.login1.policy:290
msgid "Authentication is required for hibernating the system."
msgstr ""
"Чтобы перевести систему в спящий режим, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:299
+#: src/login/org.freedesktop.login1.policy:299
msgid "Hibernate the system while other users are logged in"
msgstr ""
"Перевести систему в спящий режим, несмотря на то, что в ней работают другие "
"пользователи"
-#: src/login/org.freedesktop.login1.policy.in:300
+#: src/login/org.freedesktop.login1.policy:300
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
@@ -465,13 +465,13 @@ msgstr ""
"Чтобы перевести систему в спящий режим, несмотря на то, что в ней работают "
"другие пользователи, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:310
+#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while an application asked to inhibit it"
msgstr ""
"Перевести систему в спящий режим, несмотря на то, что приложение запросило "
"блокировку"
-#: src/login/org.freedesktop.login1.policy.in:311
+#: src/login/org.freedesktop.login1.policy:311
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
@@ -479,32 +479,32 @@ msgstr ""
"Чтобы перевести систему в спящий режим, несмотря на то, что приложение "
"запросило блокировку, необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:321
+#: src/login/org.freedesktop.login1.policy:321
msgid "Manage active sessions, users and seats"
msgstr "Управление текущими сеансами, пользователями и рабочими местами"
-#: src/login/org.freedesktop.login1.policy.in:322
+#: src/login/org.freedesktop.login1.policy:322
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
"Для управления текущими сеансами, пользователями и рабочими местами, "
"необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:331
+#: src/login/org.freedesktop.login1.policy:331
msgid "Lock or unlock active sessions"
msgstr "Заблокировать или разблокировать текущие сеансы"
-#: src/login/org.freedesktop.login1.policy.in:332
+#: src/login/org.freedesktop.login1.policy:332
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Чтобы заблокировать или разблокировать текущие сеансы, необходимо пройти "
"аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:341
+#: src/login/org.freedesktop.login1.policy:341
msgid "Allow indication to the firmware to boot to setup interface"
msgstr "Разрешить загрузку в режиме настройки прошивки материнской платы"
-#: src/login/org.freedesktop.login1.policy.in:342
+#: src/login/org.freedesktop.login1.policy:342
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
@@ -512,88 +512,88 @@ msgstr ""
"Чтобы разрешить загрузку в режиме настройки прошивки материнской платы, "
"необходимо пройти аутентификацию."
-#: src/login/org.freedesktop.login1.policy.in:351
+#: src/login/org.freedesktop.login1.policy:351
msgid "Set a wall message"
msgstr "Отправить сообщение на все терминалы"
-#: src/login/org.freedesktop.login1.policy.in:352
+#: src/login/org.freedesktop.login1.policy:352
msgid "Authentication is required to set a wall message"
msgstr ""
"Чтобы отправить сообщение на все терминалы, необходимо пройти аутентификацию."
-#: src/machine/org.freedesktop.machine1.policy.in:22
+#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
msgstr "Зайти в локальный контейнер"
-#: src/machine/org.freedesktop.machine1.policy.in:23
+#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
msgstr "Чтобы зайти в локальный контейнер, необходимо пройти аутентификацию."
-#: src/machine/org.freedesktop.machine1.policy.in:32
+#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
msgstr "Зайти на этот компьютер"
-#: src/machine/org.freedesktop.machine1.policy.in:33
+#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
msgstr "Чтобы зайти на этот компьютер, необходимо пройти аутентификацию."
-#: src/machine/org.freedesktop.machine1.policy.in:42
+#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
msgstr "Получить командную оболочку в локальном контейнере"
-#: src/machine/org.freedesktop.machine1.policy.in:43
+#: src/machine/org.freedesktop.machine1.policy:43
msgid "Authentication is required to acquire a shell in a local container."
msgstr ""
"Чтобы получить командную оболочку в локальном контейнере, необходимо пройти "
"аутентификацию."
-#: src/machine/org.freedesktop.machine1.policy.in:53
+#: src/machine/org.freedesktop.machine1.policy:53
msgid "Acquire a shell on the local host"
msgstr "Запустить командную оболочку на этом компьютере"
-#: src/machine/org.freedesktop.machine1.policy.in:54
+#: src/machine/org.freedesktop.machine1.policy:54
msgid "Authentication is required to acquire a shell on the local host."
msgstr ""
"Чтобы запустить командную оболочку на этом компьютере, необходимо пройти "
"аутентификацию."
-#: src/machine/org.freedesktop.machine1.policy.in:64
+#: src/machine/org.freedesktop.machine1.policy:64
msgid "Acquire a pseudo TTY in a local container"
msgstr "Получить псевдо-терминал в локальном контейнере"
-#: src/machine/org.freedesktop.machine1.policy.in:65
+#: src/machine/org.freedesktop.machine1.policy:65
msgid ""
"Authentication is required to acquire a pseudo TTY in a local container."
msgstr ""
"Чтобы получить псевдо-терминал в локальном контейнере, необходимо пройти "
"аутентификацию."
-#: src/machine/org.freedesktop.machine1.policy.in:74
+#: src/machine/org.freedesktop.machine1.policy:74
msgid "Acquire a pseudo TTY on the local host"
msgstr "Получить псевдо-терминал на этом компьютере"
-#: src/machine/org.freedesktop.machine1.policy.in:75
+#: src/machine/org.freedesktop.machine1.policy:75
msgid "Authentication is required to acquire a pseudo TTY on the local host."
msgstr ""
"Чтобы получить псевдо-терминал на этом компьютере, необходимо пройти "
"аутентификацию."
-#: src/machine/org.freedesktop.machine1.policy.in:84
+#: src/machine/org.freedesktop.machine1.policy:84
msgid "Manage local virtual machines and containers"
msgstr "Управление виртуальными машинами и контейнерами"
-#: src/machine/org.freedesktop.machine1.policy.in:85
+#: src/machine/org.freedesktop.machine1.policy:85
msgid ""
"Authentication is required to manage local virtual machines and containers."
msgstr ""
"Для управления виртуальными машинами и контейнерами, необходимо пройти "
"аутентификацию."
-#: src/machine/org.freedesktop.machine1.policy.in:95
+#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
msgstr "Управление образами виртуальных машин и контейнеров"
-#: src/machine/org.freedesktop.machine1.policy.in:96
+#: src/machine/org.freedesktop.machine1.policy:96
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
@@ -601,44 +601,73 @@ msgstr ""
"Для управления образами виртуальных машин и контейнеров, необходимо пройти "
"аутентификацию."
-#: src/resolve/org.freedesktop.resolve1.policy.in:22
+#: src/portable/org.freedesktop.portable1.policy:13
+msgid "Inspect a portable service"
+msgstr "Прочитать образ переносимой службы"
+
+#: src/portable/org.freedesktop.portable1.policy:14
+msgid "Authentication is required to inspect a portable service."
+msgstr "Чтобы прочитать образ переносимой службы, необходимо пройти "
+"аутентификацию."
+
+#: src/portable/org.freedesktop.portable1.policy:23
+msgid "Attach or detach a portable service"
+msgstr "Подключить или отключить переносимую службу"
+
+#: src/portable/org.freedesktop.portable1.policy:24
+msgid "Authentication is required to attach or detach a portable service."
+msgstr "Чтобы подключить или отключить переносимую службу, необходимо пройти "
+"аутентификацию."
+
+#: src/portable/org.freedesktop.portable1.policy:34
+msgid "Delete or modify portable service image"
+msgstr "Удалить или изменить образ переносимой службы"
+
+#: src/portable/org.freedesktop.portable1.policy:35
+msgid ""
+"Authentication is required to delete or modify a portable service image."
+msgstr ""
+"Чтобы удалить или изменить образ переносимой службы, необходимо пройти "
+"аутентификацию."
+
+#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
msgstr "Зарегистрировать службу в DNS-SD"
-#: src/resolve/org.freedesktop.resolve1.policy.in:23
+#: src/resolve/org.freedesktop.resolve1.policy:23
msgid "Authentication is required to register a DNS-SD service"
msgstr "Чтобы зарегистрировать службу в DNS-SD, необходимо пройти "
"аутентификацию."
-#: src/resolve/org.freedesktop.resolve1.policy.in:33
+#: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service"
msgstr "Удалить службу из DNS-SD"
-#: src/resolve/org.freedesktop.resolve1.policy.in:34
+#: src/resolve/org.freedesktop.resolve1.policy:34
msgid "Authentication is required to unregister a DNS-SD service"
msgstr "Чтобы удалить службу из DNS-SD, необходимо пройти аутентификацию."
-#: src/timedate/org.freedesktop.timedate1.policy.in:22
+#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
msgstr "Настроить системное время"
-#: src/timedate/org.freedesktop.timedate1.policy.in:23
+#: src/timedate/org.freedesktop.timedate1.policy:23
msgid "Authentication is required to set the system time."
msgstr "Чтобы настроить системное время, необходимо пройти аутентификацию."
-#: src/timedate/org.freedesktop.timedate1.policy.in:33
+#: src/timedate/org.freedesktop.timedate1.policy:33
msgid "Set system timezone"
msgstr "Настроить часовой пояс"
-#: src/timedate/org.freedesktop.timedate1.policy.in:34
+#: src/timedate/org.freedesktop.timedate1.policy:34
msgid "Authentication is required to set the system timezone."
msgstr "Чтобы настроить часовой пояс, необходимо пройти аутентификацию."
-#: src/timedate/org.freedesktop.timedate1.policy.in:43
+#: src/timedate/org.freedesktop.timedate1.policy:43
msgid "Set RTC to local timezone or UTC"
msgstr "Установить аппаратные часы по местному времени или по Гринвичу"
-#: src/timedate/org.freedesktop.timedate1.policy.in:44
+#: src/timedate/org.freedesktop.timedate1.policy:44
msgid ""
"Authentication is required to control whether the RTC stores the local or "
"UTC time."
@@ -646,11 +675,11 @@ msgstr ""
"Чтобы контролировать, установлены аппаратные часы по местному времени или по "
"Гринвичу, необходимо пройти аутентификацию."
-#: src/timedate/org.freedesktop.timedate1.policy.in:54
+#: src/timedate/org.freedesktop.timedate1.policy:53
msgid "Turn network time synchronization on or off"
msgstr "Включить или выключить синхронизацию времени по сети"
-#: src/timedate/org.freedesktop.timedate1.policy.in:55
+#: src/timedate/org.freedesktop.timedate1.policy:54
msgid ""
"Authentication is required to control whether network time synchronization "
"shall be enabled."
@@ -658,35 +687,35 @@ msgstr ""
"Чтобы включить или выключить синхронизацию времени по сети, необходимо "
"пройти аутентификацию."
-#: src/core/dbus-unit.c:496
+#: src/core/dbus-unit.c:329
msgid "Authentication is required to start '$(unit)'."
msgstr "Чтобы запустить «$(unit)», необходимо пройти аутентификацию."
-#: src/core/dbus-unit.c:497
+#: src/core/dbus-unit.c:330
msgid "Authentication is required to stop '$(unit)'."
msgstr "Чтобы остановить «$(unit)», необходимо пройти аутентификацию."
-#: src/core/dbus-unit.c:498
+#: src/core/dbus-unit.c:331
msgid "Authentication is required to reload '$(unit)'."
msgstr ""
"Чтобы заставить «$(unit)» перечитать конфигурацию, необходимо пройти "
"аутентификацию."
-#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500
+#: src/core/dbus-unit.c:332 src/core/dbus-unit.c:333
msgid "Authentication is required to restart '$(unit)'."
msgstr "Чтобы перезапустить «$(unit)», необходимо пройти аутентификацию."
-#: src/core/dbus-unit.c:607
+#: src/core/dbus-unit.c:440
msgid "Authentication is required to kill '$(unit)'."
msgstr "Чтобы убить юнит «$(unit)», необходимо пройти аутентификацию."
-#: src/core/dbus-unit.c:638
+#: src/core/dbus-unit.c:471
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr ""
"Чтобы сбросить состояние «failed» у юнита «$(unit)», необходимо пройти "
"аутентификацию."
-#: src/core/dbus-unit.c:671
+#: src/core/dbus-unit.c:504
msgid "Authentication is required to set properties on '$(unit)'."
msgstr "Чтобы изменить параметры юнита «$(unit)», необходимо пройти "
"аутентификацию."
diff --git a/po/sk.po b/po/sk.po
index e1747d8caa..7d1d092e49 100644
--- a/po/sk.po
+++ b/po/sk.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Slovak translation for systemd.
-# Copyright (C) 2017 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Dušan Kazik <prescott66@gmail.com>, 2017.
#
diff --git a/po/sr.po b/po/sr.po
index dbb109434d..422e9fa827 100644
--- a/po/sr.po
+++ b/po/sr.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
diff --git a/po/sv.po b/po/sv.po
index 4a7f3d8987..a3efebea67 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Swedish translation for systemd.
-# Copyright © 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Sebastian Rasmussen <sebras@gmail.com>, 2015.
# Andreas Henriksson <andreas@fatal.se>, 2016.
diff --git a/po/tr.po b/po/tr.po
index 71b65eaf7e..3c0a19af7b 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -1,20 +1,19 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Turkish translation for systemd.
-# Copyright (C) 2014-2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Necdet Yücel <necdetyucel@gmail.com>, 2014.
# Gökhan Gurbetoğlu <ggurbet@gmail.com>, 2015.
-# Muhammet Kara <muhammetk@gmail.com>, 2015, 2016, 2017.
+# Muhammet Kara <muhammetk@gnome.org>, 2015, 2016, 2017, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2017-10-06 13:26+0000\n"
-"PO-Revision-Date: 2017-10-06 20:59+0300\n"
-"Last-Translator: Muhammet Kara <muhammetk@gmail.com>\n"
-"Language-Team: Türkçe <gnome-turk@gnome.org>\n"
+"POT-Creation-Date: 2018-03-27 03:26+0000\n"
+"PO-Revision-Date: 2018-04-22 21:20+0300\n"
+"Last-Translator: Muhammet Kara <muhammetk@gnome.org>\n"
+"Language-Team: Turkish <gnome-turk@gnome.org>\n"
"Language: tr_TR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -22,40 +21,40 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Gtranslator 2.91.7\n"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
msgstr "Sisteme parolayı geri gönder"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+#: src/core/org.freedesktop.systemd1.policy.in:23
msgid ""
"Authentication is required to send the entered passphrase back to the system."
msgstr "Sisteme parolayı geri göndermek kimlik doğrulaması gerektiriyor."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
msgstr "Sistem servislerini veya diğer birimlerini yönet"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+#: src/core/org.freedesktop.systemd1.policy.in:34
msgid "Authentication is required to manage system services or other units."
msgstr ""
"Sistem servislerini veya diğer birimlerini yönetmek kimlik doğrulaması "
"gerektiriyor."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+#: src/core/org.freedesktop.systemd1.policy.in:43
msgid "Manage system service or unit files"
msgstr "Sistem servislerini veya birim dosyalarını yönet"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+#: src/core/org.freedesktop.systemd1.policy.in:44
msgid "Authentication is required to manage system service or unit files."
msgstr ""
"Sistem servislerini veya birim dosyalarını yönetmek kimlik doğrulaması "
"gerektiriyor."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+#: src/core/org.freedesktop.systemd1.policy.in:53
msgid "Set or unset system and service manager environment variables"
msgstr "Sistem ve servis yöneticisi ortam değişkenlerini ayarla ya da kaldır"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+#: src/core/org.freedesktop.systemd1.policy.in:54
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
@@ -63,27 +62,27 @@ msgstr ""
"Sistem ve servis yöneticisi ortam değişkenlerini ayarlamak ya da kaldırmak "
"kimlik doğrulaması gerektiriyor."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+#: src/core/org.freedesktop.systemd1.policy.in:63
msgid "Reload the systemd state"
msgstr "systemd durumunu yeniden yükle"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Authentication is required to reload the systemd state."
msgstr "systemd durumunu yeniden yüklemek kimlik doğrulaması gerektiriyor."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+#: src/hostname/org.freedesktop.hostname1.policy:22
msgid "Set host name"
msgstr "Makine adını ayarla"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+#: src/hostname/org.freedesktop.hostname1.policy:23
msgid "Authentication is required to set the local host name."
msgstr "Yerel makine adını ayarlamak kimlik doğrulaması gerektiriyor."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+#: src/hostname/org.freedesktop.hostname1.policy:32
msgid "Set static host name"
msgstr "Statik makine adı ayarla"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+#: src/hostname/org.freedesktop.hostname1.policy:33
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
@@ -91,106 +90,106 @@ msgstr ""
"Statik olarak yapılandırılmış konak makine adını ve yerel makine adını "
"ayarlamak kimlik doğrulaması gerektiriyor."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+#: src/hostname/org.freedesktop.hostname1.policy:43
msgid "Set machine information"
msgstr "Makine bilgisini ayarla"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+#: src/hostname/org.freedesktop.hostname1.policy:44
msgid "Authentication is required to set local machine information."
msgstr "Yerel makine bilgisini ayarlamak kimlik doğrulaması gerektiriyor."
-#: ../src/import/org.freedesktop.import1.policy.in.h:1
+#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
msgstr "Bir SM ya da kapsayıcı kalıbını içe aktar"
-#: ../src/import/org.freedesktop.import1.policy.in.h:2
+#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
msgstr ""
"Bir SM ya da kapsayıcı kalıbını içe aktarmak için kimlik doğrulaması "
"gereklidir"
-#: ../src/import/org.freedesktop.import1.policy.in.h:3
+#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
msgstr "Bir SM ya da kapsayıcı kalıbını dışa aktar"
-#: ../src/import/org.freedesktop.import1.policy.in.h:4
+#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
msgstr ""
"Bir SM ya da kapsayıcı kalıbını dışa aktarmak için kimlik doğrulaması "
"gereklidir"
-#: ../src/import/org.freedesktop.import1.policy.in.h:5
+#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
msgstr "Bir SM ya da kapsayıcı kalıbını indir"
-#: ../src/import/org.freedesktop.import1.policy.in.h:6
+#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
msgstr ""
"Bir SM ya da kapsayıcı kalıbını indirmek için kimlik doğrulaması gereklidir"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
msgstr "Sistem yerelini ayarla"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
msgstr "Sistem yerelini ayarlamak kimlik doğrulaması gerektiriyor."
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
msgstr "Sistem klavye ayarlarını ayarla"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
msgstr "Sistem klavye ayarlarını ayarlamak kimlik doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:1
+#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
msgstr "Uygulamaların sistemin kapanmasına engel olmasına izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:2
+#: src/login/org.freedesktop.login1.policy:23
msgid ""
"Authentication is required for an application to inhibit system shutdown."
msgstr ""
"Bir uygulamanın sistemin kapanmasına engel olması için kimlik doğrulaması "
"gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:3
+#: src/login/org.freedesktop.login1.policy:33
msgid "Allow applications to delay system shutdown"
msgstr "Uygulamaların sistemin kapanmasını geciktirmelerine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:4
+#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
msgstr ""
"Bir uygulamanın sistemin kapanmasını geciktirmesi için kimlik doğrulaması "
"gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:5
+#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
msgstr "Uygulamaların sistemin beklemeye geçmesini engellemesine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:6
+#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr ""
"Bir uygulamanın sistemin uykuya geçmesine engel olması için kimlik "
"doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:7
+#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"
msgstr "Uygulamaların sistemin beklemeye geçmesini ertelemesine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:8
+#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
msgstr ""
"Bir uygulamanın sistemin uykuya geçmesini geciktirmesi için kimlik "
"doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:9
+#: src/login/org.freedesktop.login1.policy:65
msgid "Allow applications to inhibit automatic system suspend"
msgstr ""
"Uygulamaların sistemin otomatik bekletmeye geçmesini engellemesine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:10
+#: src/login/org.freedesktop.login1.policy:66
msgid ""
"Authentication is required for an application to inhibit automatic system "
"suspend."
@@ -198,11 +197,11 @@ msgstr ""
"Bir uygulamanın sistemin otomatik olarak askıya alınmasına engel olması için "
"kimlik doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:11
+#: src/login/org.freedesktop.login1.policy:75
msgid "Allow applications to inhibit system handling of the power key"
msgstr "Uygulamaların sistemin güç tuşunun kullanımını engellemesine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:12
+#: src/login/org.freedesktop.login1.policy:76
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the power key."
@@ -210,12 +209,12 @@ msgstr ""
"Bir uygulamanın sistemin güç tuşunu idare etmesine engel olması için kimlik "
"doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:13
+#: src/login/org.freedesktop.login1.policy:86
msgid "Allow applications to inhibit system handling of the suspend key"
msgstr ""
"Uygulamaların sistemin beklet tuşunun kullanımını engellemesine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:14
+#: src/login/org.freedesktop.login1.policy:87
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
@@ -223,13 +222,13 @@ msgstr ""
"Bir uygulamanın sistemin askıya alma tuşunu idare etmesine engel olması için "
"kimlik doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:15
+#: src/login/org.freedesktop.login1.policy:97
msgid "Allow applications to inhibit system handling of the hibernate key"
msgstr ""
"Uygulamaların sistemin uykuya geçme tuşunun kullanımını engellemesine izin "
"ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:16
+#: src/login/org.freedesktop.login1.policy:98
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
@@ -237,12 +236,12 @@ msgstr ""
"Bir uygulamanın sistemin hazırda bekletme tuşunu idare etmesine engel olması "
"için kimlik doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:17
+#: src/login/org.freedesktop.login1.policy:107
msgid "Allow applications to inhibit system handling of the lid switch"
msgstr ""
"Uygulamaların sistemin kapak anahtarının kullanımını engellemesine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:18
+#: src/login/org.freedesktop.login1.policy:108
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
@@ -250,59 +249,59 @@ msgstr ""
"Bir uygulamanın sistemin kapak anahtarını idare etmesine engel olması için "
"kimlik doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:19
+#: src/login/org.freedesktop.login1.policy:117
msgid "Allow non-logged-in user to run programs"
msgstr "Oturum açmamış kullanıcının program çalıştırmasına izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: src/login/org.freedesktop.login1.policy:118
msgid "Explicit request is required to run programs as a non-logged-in user."
msgstr ""
"Oturum açmamış bir kullanıcı olarak program çalıştırmak için açıkça istekte "
"bulunulması gerekir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: src/login/org.freedesktop.login1.policy:127
msgid "Allow non-logged-in users to run programs"
msgstr "Oturum açmamış kullanıcıların program çalıştırmasına izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: src/login/org.freedesktop.login1.policy:128
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
"Oturum açmamış bir kullanıcı olarak program çalıştırmak için kimlik "
"doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
msgstr "Aygıtların yuvaya takılmasına izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required for attaching a device to a seat."
msgstr ""
"Bir aygıtın yuvaya takılmasına izin vermek kimlik doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
msgstr "Aygıtın yuvaya eklenmesini sıfırla"
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: src/login/org.freedesktop.login1.policy:149
msgid ""
"Authentication is required for resetting how devices are attached to seats."
msgstr ""
"Aygıtların yuvalara nasıl takıldığını sıfırlamak kimlik doğrulama "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: src/login/org.freedesktop.login1.policy:158
msgid "Power off the system"
msgstr "Sistemi kapat"
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: src/login/org.freedesktop.login1.policy:159
msgid "Authentication is required for powering off the system."
msgstr "Sistemi kapatmak için kimlik doğrulaması gerekiyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system while other users are logged in"
msgstr "Diğer kullanıcılar oturum açmışken sistemi kapat"
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: src/login/org.freedesktop.login1.policy:170
msgid ""
"Authentication is required for powering off the system while other users are "
"logged in."
@@ -310,11 +309,11 @@ msgstr ""
"Diğer kullanıcılar oturum açmışken sistemi kapatmak kimlik doğrulaması "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: src/login/org.freedesktop.login1.policy:180
msgid "Power off the system while an application asked to inhibit it"
msgstr "Bir uygulama engellenmesini isterken sistemi kapat"
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: src/login/org.freedesktop.login1.policy:181
msgid ""
"Authentication is required for powering off the system while an application "
"asked to inhibit it."
@@ -322,19 +321,19 @@ msgstr ""
"Bir uygulama engellenmesini isterken sistemi kapatmak kimlik doğrulaması "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: src/login/org.freedesktop.login1.policy:191
msgid "Reboot the system"
msgstr "Sistemi yeniden başlat"
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: src/login/org.freedesktop.login1.policy:192
msgid "Authentication is required for rebooting the system."
msgstr "Sistemi yeniden başlatmak kimlik doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system while other users are logged in"
msgstr "Diğer kullanıcılar oturum açmışken sistemi yeniden başlat"
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: src/login/org.freedesktop.login1.policy:203
msgid ""
"Authentication is required for rebooting the system while other users are "
"logged in."
@@ -342,11 +341,11 @@ msgstr ""
"Diğer kullanıcılar oturum açmışken sistemi yeniden başlatmak kimlik "
"doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while an application asked to inhibit it"
msgstr "Bir uygulama engellenmesini isterken sistemi yeniden başlat"
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: src/login/org.freedesktop.login1.policy:214
msgid ""
"Authentication is required for rebooting the system while an application "
"asked to inhibit it."
@@ -354,25 +353,19 @@ msgstr ""
"Bir uygulama engellenmesini isterken sistemi yeniden başlatmak kimlik "
"doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
-#| msgid "Hibernate the system"
+#: src/login/org.freedesktop.login1.policy:224
msgid "Halt the system"
msgstr "Sistemi durdur"
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
-#| msgid "Authentication is required for hibernating the system."
+#: src/login/org.freedesktop.login1.policy:225
msgid "Authentication is required for halting the system."
msgstr "Sistemi durdurmak kimlik doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
-#| msgid "Hibernate the system while other users are logged in"
+#: src/login/org.freedesktop.login1.policy:235
msgid "Halt the system while other users are logged in"
msgstr "Diğer kullanıcılar oturum açmışken sistemi durdur"
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
-#| msgid ""
-#| "Authentication is required for hibernating the system while other users "
-#| "are logged in."
+#: src/login/org.freedesktop.login1.policy:236
msgid ""
"Authentication is required for halting the system while other users are "
"logged in."
@@ -380,15 +373,11 @@ msgstr ""
"Diğer kullanıcılar oturum açmışken sistemi durdurmak kimlik doğrulaması "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
-#| msgid "Hibernate the system while an application asked to inhibit it"
+#: src/login/org.freedesktop.login1.policy:246
msgid "Halt the system while an application asked to inhibit it"
msgstr "Bir uygulama engellenmesini isterken sistemi durdur"
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
-#| msgid ""
-#| "Authentication is required for hibernating the system while an "
-#| "application asked to inhibit it."
+#: src/login/org.freedesktop.login1.policy:247
msgid ""
"Authentication is required for halting the system while an application asked "
"to inhibit it."
@@ -396,19 +385,19 @@ msgstr ""
"Bir uygulama engellenmesini isterken sistemi durdurmak kimlik doğrulaması "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
msgstr "Sistemi askıya al"
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: src/login/org.freedesktop.login1.policy:258
msgid "Authentication is required for suspending the system."
msgstr "Sistemi askıya almak kimlik doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: src/login/org.freedesktop.login1.policy:267
msgid "Suspend the system while other users are logged in"
msgstr "Diğer kullanıcılar oturum açmışken sistemi askıya al"
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: src/login/org.freedesktop.login1.policy:268
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
@@ -416,11 +405,11 @@ msgstr ""
"Diğer kullanıcılar oturum açmışken sistemi askıya almak kimlik doğrulaması "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: src/login/org.freedesktop.login1.policy:278
msgid "Suspend the system while an application asked to inhibit it"
msgstr "Bir uygulama engellenmesini isterken sistemi askıya al"
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: src/login/org.freedesktop.login1.policy:279
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
@@ -428,19 +417,19 @@ msgstr ""
"Bir uygulama engellenmesini isterken sistemi askıya almak kimlik doğrulaması "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: src/login/org.freedesktop.login1.policy:289
msgid "Hibernate the system"
msgstr "Sistemi hazırda beklet"
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: src/login/org.freedesktop.login1.policy:290
msgid "Authentication is required for hibernating the system."
msgstr "Sistemi hazırda bekletmek kimlik doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: src/login/org.freedesktop.login1.policy:299
msgid "Hibernate the system while other users are logged in"
msgstr "Diğer kullanıcılar oturum açmışken sistemi hazırda beklet"
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: src/login/org.freedesktop.login1.policy:300
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
@@ -448,11 +437,11 @@ msgstr ""
"Diğer kullanıcılar oturum açmışken sistemi hazırda bekletmek kimlik "
"doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while an application asked to inhibit it"
msgstr "Bir uygulama engellenmesini isterken sistemi hazırda beklet"
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: src/login/org.freedesktop.login1.policy:311
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
@@ -460,33 +449,33 @@ msgstr ""
"Bir uygulama engellenmesini isterken sistemi hazırda bekletmek kimlik "
"doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:57
+#: src/login/org.freedesktop.login1.policy:321
msgid "Manage active sessions, users and seats"
msgstr "Aktif oturumları, kullanıcıları ve yuvaları yönet"
-#: ../src/login/org.freedesktop.login1.policy.in.h:58
+#: src/login/org.freedesktop.login1.policy:322
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
"Aktif oturumları, kullanıcıları ve yuvaları yönetmek için kimlik doğrulaması "
"gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:59
+#: src/login/org.freedesktop.login1.policy:331
msgid "Lock or unlock active sessions"
msgstr "Aktif oturumları kilitle ya da kilidini aç"
-#: ../src/login/org.freedesktop.login1.policy.in.h:60
+#: src/login/org.freedesktop.login1.policy:332
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Aktif oturumları kilitlemek ve bunların kilidini açmak için kimlik "
"doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:61
+#: src/login/org.freedesktop.login1.policy:341
msgid "Allow indication to the firmware to boot to setup interface"
msgstr ""
"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:62
+#: src/login/org.freedesktop.login1.policy:342
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
@@ -494,85 +483,85 @@ msgstr ""
"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesi için kimlik "
"doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:63
+#: src/login/org.freedesktop.login1.policy:351
msgid "Set a wall message"
msgstr "Bir duvar mesajı ayarla"
-#: ../src/login/org.freedesktop.login1.policy.in.h:64
+#: src/login/org.freedesktop.login1.policy:352
msgid "Authentication is required to set a wall message"
msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
msgstr "Yerel kapsayıcıya giriş yap"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
msgstr "Yerel kapsayıcıda oturum açmak için kimlik doğrulaması gereklidir."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
msgstr "Yerel (ana) makineye giriş yap"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
msgstr "Yerel (ana) makinede oturum açmak için kimlik doğrulaması gereklidir."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
msgstr "Yerel kapsayıcıda kabuk (shell) aç"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: src/machine/org.freedesktop.machine1.policy:43
msgid "Authentication is required to acquire a shell in a local container."
msgstr ""
"Yerel kapsayıcıda kabuk (shell) açmak için kimlik doğrulaması gereklidir."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+#: src/machine/org.freedesktop.machine1.policy:53
msgid "Acquire a shell on the local host"
msgstr "Yerel (ana) makinede kabuk (shell) aç"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+#: src/machine/org.freedesktop.machine1.policy:54
msgid "Authentication is required to acquire a shell on the local host."
msgstr ""
"Yerel (ana) makinede kabuk (shell) açmak için kimlik doğrulaması gereklidir."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#: src/machine/org.freedesktop.machine1.policy:64
msgid "Acquire a pseudo TTY in a local container"
msgstr "Yerel kapsayıcıda sözde (pseudo) TTY al"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#: src/machine/org.freedesktop.machine1.policy:65
msgid ""
"Authentication is required to acquire a pseudo TTY in a local container."
msgstr ""
"Yerel kapsayıcıda sözde (pseudo) TTY almak için kimlik doğrulaması "
"gereklidir."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+#: src/machine/org.freedesktop.machine1.policy:74
msgid "Acquire a pseudo TTY on the local host"
msgstr "Yerel (ana) makinede sözde (pseudo) TTY al"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+#: src/machine/org.freedesktop.machine1.policy:75
msgid "Authentication is required to acquire a pseudo TTY on the local host."
msgstr ""
"Yerel (ana) makinede sözde (pseudo) TTY almak için kimlik doğrulaması "
"gereklidir."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+#: src/machine/org.freedesktop.machine1.policy:84
msgid "Manage local virtual machines and containers"
msgstr "Yerel sanal makineleri ve kapsayıcıları yönet"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+#: src/machine/org.freedesktop.machine1.policy:85
msgid ""
"Authentication is required to manage local virtual machines and containers."
msgstr ""
"Yerel sanal makineleri ve kapsayıcıları yönetmek için kimlik doğrulaması "
"gereklidir."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
msgstr "Yerel sanal makine ve kapsayıcı kalıplarını yönet"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+#: src/machine/org.freedesktop.machine1.policy:96
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
@@ -580,27 +569,46 @@ msgstr ""
"Yerel sanal makineler ve kapsayıcı kalıplarını yönetmek için kimlik "
"doğrulaması gereklidir."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+#: src/resolve/org.freedesktop.resolve1.policy:22
+msgid "Register a DNS-SD service"
+msgstr "Bir DNS-SD hizmeti kaydet"
+
+#: src/resolve/org.freedesktop.resolve1.policy:23
+#| msgid "Authentication is required to set a wall message"
+msgid "Authentication is required to register a DNS-SD service"
+msgstr "Bir DNS-SD hizmeti kaydetmek için kimlik doğrulaması gereklidir"
+
+#: src/resolve/org.freedesktop.resolve1.policy:33
+msgid "Unregister a DNS-SD service"
+msgstr "Bir DNS-SD hizmetinin kaydını sil"
+
+#: src/resolve/org.freedesktop.resolve1.policy:34
+#| msgid "Authentication is required to set a wall message"
+msgid "Authentication is required to unregister a DNS-SD service"
+msgstr ""
+"Bir DNS-SD hizmetinin kaydını silmek için kimlik doğrulaması gereklidir"
+
+#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
msgstr "Sistem zamanını ayarla"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+#: src/timedate/org.freedesktop.timedate1.policy:23
msgid "Authentication is required to set the system time."
msgstr "Sistem zamanını ayarlamak kimlik doğrulaması gerektiriyor."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+#: src/timedate/org.freedesktop.timedate1.policy:33
msgid "Set system timezone"
msgstr "Sistem zaman dilimini ayarla"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+#: src/timedate/org.freedesktop.timedate1.policy:34
msgid "Authentication is required to set the system timezone."
msgstr "Sistem zaman dilimini ayarlamak kimlik doğrulaması gerektiriyor."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+#: src/timedate/org.freedesktop.timedate1.policy:43
msgid "Set RTC to local timezone or UTC"
msgstr "Gerçek zamanlı saat olarak yerel zaman dilimini veya UTC'yi ayarla"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+#: src/timedate/org.freedesktop.timedate1.policy:44
msgid ""
"Authentication is required to control whether the RTC stores the local or "
"UTC time."
@@ -608,44 +616,44 @@ msgstr ""
"Gerçek zamanlı saat olarak yerel zaman dilimini veya UTC'yi ayarlamak kimlik "
"doğrulaması gerektiriyor."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+#: src/timedate/org.freedesktop.timedate1.policy:54
msgid "Turn network time synchronization on or off"
msgstr "Ağ zaman eş zamanlamasını aç veya kapat"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+#: src/timedate/org.freedesktop.timedate1.policy:55
msgid ""
"Authentication is required to control whether network time synchronization "
"shall be enabled."
msgstr ""
"Ağ zaman eş zamanlamasını kontrol etmek kimlik doğrulaması gerektiriyor."
-#: ../src/core/dbus-unit.c:458
+#: src/core/dbus-unit.c:496
msgid "Authentication is required to start '$(unit)'."
msgstr "'$(unit)' başlatmak için kimlik doğrulaması gereklidir."
-#: ../src/core/dbus-unit.c:459
+#: src/core/dbus-unit.c:497
msgid "Authentication is required to stop '$(unit)'."
msgstr "'$(unit)' durdurmak için kimlik doğrulaması gereklidir."
-#: ../src/core/dbus-unit.c:460
+#: src/core/dbus-unit.c:498
msgid "Authentication is required to reload '$(unit)'."
msgstr "'$(unit)' yeniden yüklemek için kimlik doğrulaması gereklidir."
-#: ../src/core/dbus-unit.c:461 ../src/core/dbus-unit.c:462
+#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500
msgid "Authentication is required to restart '$(unit)'."
msgstr "'$(unit)' yeniden başlatmak için kimlik doğrulaması gereklidir."
-#: ../src/core/dbus-unit.c:569
+#: src/core/dbus-unit.c:607
msgid "Authentication is required to kill '$(unit)'."
msgstr "'$(unit)' sonlandırmak için kimlik doğrulaması gereklidir."
-#: ../src/core/dbus-unit.c:600
+#: src/core/dbus-unit.c:638
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr ""
"'$(unit)'in \"failed\" (başarısız) durumunu sıfırlamak için kimlik "
"doğrulaması gereklidir."
-#: ../src/core/dbus-unit.c:633
+#: src/core/dbus-unit.c:671
msgid "Authentication is required to set properties on '$(unit)'."
msgstr ""
"'$(unit)' üzerindeki özellikleri ayarlamak için kimlik doğrulaması "
diff --git a/po/uk.po b/po/uk.po
index 31e5f55beb..0862f13a7d 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -1,16 +1,14 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
# Ukrainian translation for systemd.
-# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Eugene Melnik <jeka7js@gmail.com>, 2014.
-# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016.
+# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016, 2018.
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-01-11 09:21+0200\n"
-"PO-Revision-Date: 2016-01-11 11:00+0300\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2018-03-27 03:26+0000\n"
+"PO-Revision-Date: 2018-05-11 23:16+0300\n"
"Last-Translator: Daniel Korostil <ted.korostiled@gmail.com>\n"
"Language-Team: linux.org.ua\n"
"Language: uk\n"
@@ -21,551 +19,623 @@ msgstr ""
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Virtaal 0.7.1\n"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
msgstr "Надіслати пароль назад у систему"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+#: src/core/org.freedesktop.systemd1.policy.in:23
msgid ""
"Authentication is required to send the entered passphrase back to the system."
-msgstr "Засвідчення потрібно, щоб надіслати введений пароль назад у систему."
+msgstr "Потрібна автентифікація, щоб надіслати введений пароль назад у систему."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
-msgstr "Керувати системними службами й іншими одиницями"
+msgstr "Керувати системними службами й іншими одиницями systemd"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+#: src/core/org.freedesktop.systemd1.policy.in:34
msgid "Authentication is required to manage system services or other units."
msgstr ""
-"Засвідчення потрібно, щоб керувати системними службами й іншими одиницями."
+"Потрібна автентифікація, щоб керувати системними службами й іншими одиницями systemd."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+#: src/core/org.freedesktop.systemd1.policy.in:43
msgid "Manage system service or unit files"
-msgstr "Керувати системними службами й файлами одиниць"
+msgstr "Керувати системними службами й одиницями systemd"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+#: src/core/org.freedesktop.systemd1.policy.in:44
msgid "Authentication is required to manage system service or unit files."
msgstr ""
-"Засвідчення потрібно, щоб керувати системними службами й файлами одиниць."
+"Потрібна автентифікація, щоб керувати системними службами й одиницями systemd."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+#: src/core/org.freedesktop.systemd1.policy.in:53
msgid "Set or unset system and service manager environment variables"
msgstr ""
"Встановити або забрати змінну середовища з керування службами і системою"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+#: src/core/org.freedesktop.systemd1.policy.in:54
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
msgstr ""
-"Засвідчення потрібно, щоб установити або забрати змінні середовища з "
+"Потрібна автентифікація, щоб установити або забрати змінні середовища з "
"керування службами і системою."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+#: src/core/org.freedesktop.systemd1.policy.in:63
msgid "Reload the systemd state"
msgstr "Перезапустити стан системи"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Authentication is required to reload the systemd state."
-msgstr "Засвідчення потрібно, щоб перезапустити стан системи."
+msgstr "Потрібна автентифікація, щоб перезапустити стан системи."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+#: src/hostname/org.freedesktop.hostname1.policy:22
msgid "Set host name"
msgstr "Встановити назву вузла"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+#: src/hostname/org.freedesktop.hostname1.policy:23
msgid "Authentication is required to set the local host name."
-msgstr "Засвідчення потрібне, щоб встановити назву локального вузла."
+msgstr "Потрібна автентифікація, щоб встановити назву локального вузла."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+#: src/hostname/org.freedesktop.hostname1.policy:32
msgid "Set static host name"
msgstr "Встановити статичну назву вузла"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+#: src/hostname/org.freedesktop.hostname1.policy:33
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
msgstr ""
-"Засвідчення потрібне, щоб вказати статично налаштовану назву локального "
+"Потрібна автентифікація, щоб вказати статично налаштовану назву локального "
"вузла, так само й форматовану."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+#: src/hostname/org.freedesktop.hostname1.policy:43
msgid "Set machine information"
msgstr "Встановити інформацію про машину"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+#: src/hostname/org.freedesktop.hostname1.policy:44
msgid "Authentication is required to set local machine information."
-msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
+msgstr "Потрібна автентифікація, щоб вказати локальну інформацію про машини."
-#: ../src/import/org.freedesktop.import1.policy.in.h:1
+#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
msgstr "Імпортувати образ контейнера або віртуальної машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:2
+#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
msgstr ""
-"Засвідчення потрібно, щоб імпортувати образ контейнера або віртуальної машини"
+"Потрібна автентифікація, щоб імпортувати образ контейнера або віртуальної машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:3
+#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
msgstr "Експортувати образ контейнера або віртуальної машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:4
+#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
msgstr ""
-"Засвідчення потрібно, щоб експортувати образ контейнера або віртуальної "
+"Потрібна автентифікація, щоб експортувати образ контейнера або віртуальної "
"машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:5
+#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
msgstr "Звантажити образ контейнера або віртуальної машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:6
+#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
msgstr ""
-"Засвідчення потрібно, щоб звантажити образ контейнера або віртуальної машини"
+"Потрібна автентифікація, щоб звантажити образ контейнера або віртуальної машини"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
msgstr "Вказати системну локаль"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
-msgstr "Засвідчення потрібно, щоб встановити системну локаль."
+msgstr "Потрібна автентифікація, щоб встановити системну локаль."
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
msgstr "Вказати налаштування системної клавіатури"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
-msgstr "Засвідчення потрібно, щоб вказати налаштування системної клавіатури."
+msgstr "Потрібна автентифікація, щоб вказати налаштування системної клавіатури."
-#: ../src/login/org.freedesktop.login1.policy.in.h:1
+#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
msgstr "Дозволити програмам перешкоджати вимкненню системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:2
+#: src/login/org.freedesktop.login1.policy:23
msgid ""
"Authentication is required for an application to inhibit system shutdown."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам перешкоджати вимкненню системи."
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати вимкненню системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:3
+#: src/login/org.freedesktop.login1.policy:33
msgid "Allow applications to delay system shutdown"
msgstr "Дозволити програмам затримувати вимкнення системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:4
+#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам затримувати вимкнення системи."
+"Потрібна автентифікація, щоб дозволити програмам затримувати вимкнення системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:5
+#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
msgstr "Дозволити програмам перешкоджати засинанню системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:6
+#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам перешкоджати засинанню системи."
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати засинанню системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:7
+#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"
msgstr "Дозволити програмами затримувати засинання системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:8
+#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам затримувати засинання системи."
+"Потрібна автентифікація, щоб дозволити програмам затримувати засинання системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:9
+#: src/login/org.freedesktop.login1.policy:65
msgid "Allow applications to inhibit automatic system suspend"
msgstr "Дозволити програмам перешкоджати автоматичному призупиненню системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:10
+#: src/login/org.freedesktop.login1.policy:66
msgid ""
"Authentication is required for an application to inhibit automatic system "
"suspend."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам перешкоджати автоматичному "
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати автоматичному "
"призупиненню системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:11
+#: src/login/org.freedesktop.login1.policy:75
msgid "Allow applications to inhibit system handling of the power key"
msgstr "Дозволити програмам перешкоджати обробленню системою клавіші живлення"
-#: ../src/login/org.freedesktop.login1.policy.in.h:12
+#: src/login/org.freedesktop.login1.policy:76
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the power key."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню "
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню "
"системою клавіші живлення."
-#: ../src/login/org.freedesktop.login1.policy.in.h:13
+#: src/login/org.freedesktop.login1.policy:86
msgid "Allow applications to inhibit system handling of the suspend key"
msgstr ""
"Дозволити програмам перешкоджати обробленню системою клавіші призупинення"
-#: ../src/login/org.freedesktop.login1.policy.in.h:14
+#: src/login/org.freedesktop.login1.policy:87
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню "
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню "
"системою клавіші призупинення."
-#: ../src/login/org.freedesktop.login1.policy.in.h:15
+#: src/login/org.freedesktop.login1.policy:97
msgid "Allow applications to inhibit system handling of the hibernate key"
msgstr ""
"Дозволити програмам перешкоджати обробленню системою клавіші присипання"
-#: ../src/login/org.freedesktop.login1.policy.in.h:16
+#: src/login/org.freedesktop.login1.policy:98
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню "
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню "
"системою клавіші присипання."
-#: ../src/login/org.freedesktop.login1.policy.in.h:17
+#: src/login/org.freedesktop.login1.policy:107
msgid "Allow applications to inhibit system handling of the lid switch"
msgstr ""
"Дозволити програмам перешкоджати обробленню системою клавіші перемикання "
"кришки"
-#: ../src/login/org.freedesktop.login1.policy.in.h:18
+#: src/login/org.freedesktop.login1.policy:108
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
msgstr ""
-"Засвідчення потрібно, щоб дозволити програмам перешкоджати обробленню "
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню "
"системою клавіші перемикання кришки."
-#: ../src/login/org.freedesktop.login1.policy.in.h:19
+#: src/login/org.freedesktop.login1.policy:117
+#| msgid "Allow non-logged-in users to run programs"
+msgid "Allow non-logged-in user to run programs"
+msgstr "Дозволити незареєстрованим користувачам запускати програми"
+
+#: src/login/org.freedesktop.login1.policy:118
+#| msgid "Authentication is required to run programs as a non-logged-in user."
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам запускати "
+"програми."
+
+#: src/login/org.freedesktop.login1.policy:127
msgid "Allow non-logged-in users to run programs"
msgstr "Дозволити незареєстрованим користувачам запускати програми"
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: src/login/org.freedesktop.login1.policy:128
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
-"Засвідчення потрібно, щоб дозволити незареєстрованим користувачам запускати "
+"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам запускати "
"програми."
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
msgstr "Дозволити під'єднання пристроїв до місць"
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required for attaching a device to a seat."
-msgstr "Засвідчення потрібно, щоб під'єднувати пристрої до місць."
+msgstr "Потрібна автентифікація, щоб під'єднувати пристрої до місць."
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
msgstr "Очисний пристрій для під'єднань до місця"
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: src/login/org.freedesktop.login1.policy:149
msgid ""
"Authentication is required for resetting how devices are attached to seats."
-msgstr "Засвідчення потрібно, щоб перезапустити спосіб під'єднання до місць."
+msgstr "Потрібна автентифікація, щоб перезапустити спосіб під'єднання до місць."
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: src/login/org.freedesktop.login1.policy:158
msgid "Power off the system"
msgstr "Вимкнути систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: src/login/org.freedesktop.login1.policy:159
msgid "Authentication is required for powering off the system."
-msgstr "Засвідчення потрібно, щоб вимкнути систему."
+msgstr "Потрібна автентифікація, щоб вимкнути систему."
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system while other users are logged in"
msgstr "Вимкнути систему, коли інші користувачі ще в ній"
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: src/login/org.freedesktop.login1.policy:170
msgid ""
"Authentication is required for powering off the system while other users are "
"logged in."
msgstr ""
-"Засвідчення потрібно, щоб вимкнути систему, коли інші користувачі в ній."
+"Потрібна автентифікація, щоб вимкнути систему, коли інші користувачі в ній."
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: src/login/org.freedesktop.login1.policy:180
msgid "Power off the system while an application asked to inhibit it"
msgstr "Вимкнути систему, коли програми намагаються перешкодити цьому"
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: src/login/org.freedesktop.login1.policy:181
msgid ""
"Authentication is required for powering off the system while an application "
"asked to inhibit it."
msgstr ""
-"Засвідчення потрібно, щоб вимкнути систему, коли програми намагаються "
+"Потрібна автентифікація, щоб вимкнути систему, коли програми намагаються "
"перешкодити цьому."
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: src/login/org.freedesktop.login1.policy:191
msgid "Reboot the system"
msgstr "Перезавантажити систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: src/login/org.freedesktop.login1.policy:192
msgid "Authentication is required for rebooting the system."
msgstr "Для перезавантаження системи необхідна ідентифікація."
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system while other users are logged in"
msgstr "Перезавантажити, якщо інші користувачі в системі"
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: src/login/org.freedesktop.login1.policy:203
msgid ""
"Authentication is required for rebooting the system while other users are "
"logged in."
msgstr ""
-"Засвідчення потрібно, щоб перезапустити систему, коли інші користувачі в ній."
+"Потрібна автентифікація, щоб перезапустити систему, коли інші користувачі в ній."
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while an application asked to inhibit it"
msgstr "Перезапустити систему, коли програми намагаються перешкодити цьому"
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: src/login/org.freedesktop.login1.policy:214
msgid ""
"Authentication is required for rebooting the system while an application "
"asked to inhibit it."
msgstr ""
-"Засвідчення потрібно, щоб перезапустити систему, коли програми намагаються "
+"Потрібна автентифікація, щоб перезапустити систему, коли програми намагаються "
"перешкодити цьому."
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: src/login/org.freedesktop.login1.policy:224
+#| msgid "Hibernate the system"
+msgid "Halt the system"
+msgstr "Зупинити систему"
+
+#: src/login/org.freedesktop.login1.policy:225
+#| msgid "Authentication is required for hibernating the system."
+msgid "Authentication is required for halting the system."
+msgstr "Потрібна автентифікація, щоб зупинити систему."
+
+#: src/login/org.freedesktop.login1.policy:235
+#| msgid "Hibernate the system while other users are logged in"
+msgid "Halt the system while other users are logged in"
+msgstr "Зупинити систему, коли інші користувачі в ній"
+
+#: src/login/org.freedesktop.login1.policy:236
+#| msgid ""
+#| "Authentication is required for hibernating the system while other users "
+#| "are logged in."
+msgid ""
+"Authentication is required for halting the system while other users are "
+"logged in."
+msgstr ""
+"Потрібна автентифікація, щоб зупинити систему, коли інші користувачі в ній."
+
+#: src/login/org.freedesktop.login1.policy:246
+#| msgid "Hibernate the system while an application asked to inhibit it"
+msgid "Halt the system while an application asked to inhibit it"
+msgstr "Зупинити систему, коли програми намагаються перешкодити цьому"
+
+#: src/login/org.freedesktop.login1.policy:247
+#| msgid ""
+#| "Authentication is required for hibernating the system while an "
+#| "application asked to inhibit it."
+msgid ""
+"Authentication is required for halting the system while an application asked "
+"to inhibit it."
+msgstr ""
+"Потрібна автентифікація, щоб зупинити систему, коли програми намагаються "
+"перешкодити цьому."
+
+#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
msgstr "Призупинити систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: src/login/org.freedesktop.login1.policy:258
msgid "Authentication is required for suspending the system."
-msgstr "Засвідчення потрібно, щоб призупинити систему."
+msgstr "Потрібна автентифікація, щоб призупинити систему."
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: src/login/org.freedesktop.login1.policy:267
msgid "Suspend the system while other users are logged in"
msgstr "Призупинити систему, коли інші користувачі в ній"
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: src/login/org.freedesktop.login1.policy:268
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
msgstr ""
-"Засвідчення потрібно, щоб призупинити систему, коли інші користувачі в ній."
+"Потрібна автентифікація, щоб призупинити систему, коли інші користувачі в ній."
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: src/login/org.freedesktop.login1.policy:278
msgid "Suspend the system while an application asked to inhibit it"
msgstr "Призупинити систему, коли програми намагаються перешкодити цьому"
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: src/login/org.freedesktop.login1.policy:279
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
msgstr ""
-"Засвідчення потрібно, щоб призупинити систему, коли програми намагаються "
+"Потрібна автентифікація, щоб призупинити систему, коли програми намагаються "
"перешкодити цьому."
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: src/login/org.freedesktop.login1.policy:289
msgid "Hibernate the system"
msgstr "Приспати систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: src/login/org.freedesktop.login1.policy:290
msgid "Authentication is required for hibernating the system."
-msgstr "Засвідчення потрібно, щоб приспати систему."
+msgstr "Потрібна автентифікація, щоб приспати систему."
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: src/login/org.freedesktop.login1.policy:299
msgid "Hibernate the system while other users are logged in"
msgstr "Приспати систему, коли інші користувачі в ній"
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: src/login/org.freedesktop.login1.policy:300
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
msgstr ""
-"Засвідчення потрібно, щоб присипання систему, коли інші користувачі в ній."
+"Потрібна автентифікація, щоб присипання систему, коли інші користувачі в ній."
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while an application asked to inhibit it"
msgstr "Приспати систему, коли програми намагаються перешкодити цьому"
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: src/login/org.freedesktop.login1.policy:311
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
msgstr ""
-"Засвідчення потрібно, щоб приспати систему, коли програми намагаються "
+"Потрібна автентифікація, щоб приспати систему, коли програми намагаються "
"перешкодити цьому."
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: src/login/org.freedesktop.login1.policy:321
msgid "Manage active sessions, users and seats"
msgstr "Керувати сеансами, користувачами і робочими місцями"
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: src/login/org.freedesktop.login1.policy:322
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
-"Засвідчення потрібно, щоб керувати сеансами, користувачами і робочими "
+"Потрібна автентифікація, щоб керувати сеансами, користувачами і робочими "
"місцями."
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: src/login/org.freedesktop.login1.policy:331
msgid "Lock or unlock active sessions"
msgstr "Заблокувати або розблокувати сеанси"
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: src/login/org.freedesktop.login1.policy:332
msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Засвідчення потрібно, щоб заблокувати або розблокувати сеанси."
+msgstr "Потрібна автентифікація, щоб заблокувати або розблокувати сеанси."
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: src/login/org.freedesktop.login1.policy:341
msgid "Allow indication to the firmware to boot to setup interface"
msgstr "Дозволити мікрокоду визначати, чи завантажувати інтерфейс встановлення"
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: src/login/org.freedesktop.login1.policy:342
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
msgstr ""
-"Засвідчення потрібне, щоб дозволити мікрокоду визначати, чи завантажувати "
+"Потрібна автентифікація, щоб дозволити мікрокоду визначати, чи завантажувати "
"інтерфейс встановлення."
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: src/login/org.freedesktop.login1.policy:351
msgid "Set a wall message"
msgstr "Вказати повідомлення на стіні"
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: src/login/org.freedesktop.login1.policy:352
msgid "Authentication is required to set a wall message"
-msgstr "Засвідчення потрібне, щоб вказати повідомлення на стіні"
+msgstr "Потрібна автентифікація, щоб вказати повідомлення на стіні"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
msgstr "Увійти в локальний контейнер"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
-msgstr "Засвідчення потрібне, щоб увійти в локальний контейнер."
+msgstr "Потрібна автентифікація, щоб увійти в локальний контейнер."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
msgstr "Увійти в локальний вузол"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
-msgstr "Засвідчення потрібне, щоб увійти в локальний вузол."
+msgstr "Потрібна автентифікація, щоб увійти в локальний вузол."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
msgstr "Перейняти оболонку в локальному контейнері"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: src/machine/org.freedesktop.machine1.policy:43
msgid "Authentication is required to acquire a shell in a local container."
-msgstr "Засвідчення потрібне, щоб перейняти оболонку в локальному контейнері."
+msgstr "Потрібна автентифікація, щоб перейняти оболонку в локальному контейнері."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+#: src/machine/org.freedesktop.machine1.policy:53
msgid "Acquire a shell on the local host"
msgstr "Перейняти оболонку на локальному вузлі"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+#: src/machine/org.freedesktop.machine1.policy:54
msgid "Authentication is required to acquire a shell on the local host."
-msgstr "Засвідчення потрібне, щоб перейняти оболонку на локальному вузлі."
+msgstr "Потрібна автентифікація, щоб перейняти оболонку на локальному вузлі."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#: src/machine/org.freedesktop.machine1.policy:64
msgid "Acquire a pseudo TTY in a local container"
msgstr "Перейняти псевдо TTY в локальному контейнері"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#: src/machine/org.freedesktop.machine1.policy:65
msgid ""
"Authentication is required to acquire a pseudo TTY in a local container."
-msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY в локальному контейнері."
+msgstr ""
+"Потрібна автентифікація, щоб перейняти псевдо TTY в локальному контейнері."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+#: src/machine/org.freedesktop.machine1.policy:74
msgid "Acquire a pseudo TTY on the local host"
msgstr "Перейняти псевдо TTY на локальному вузлі"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+#: src/machine/org.freedesktop.machine1.policy:75
msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY на локальному вузлі."
+msgstr "Потрібна автентифікація, щоб перейняти псевдо TTY на локальному вузлі."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+#: src/machine/org.freedesktop.machine1.policy:84
msgid "Manage local virtual machines and containers"
msgstr "Керувати локальними віртуальними машинами і контейнерами"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+#: src/machine/org.freedesktop.machine1.policy:85
msgid ""
"Authentication is required to manage local virtual machines and containers."
msgstr ""
-"Засвідчення потрібно, щоб керувати локальними віртуальними машинами і "
+"Потрібна автентифікація, щоб керувати локальними віртуальними машинами і "
"контейнерами."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
msgstr "Керувати локальними образами віртуальних машин і контейнерів"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+#: src/machine/org.freedesktop.machine1.policy:96
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
msgstr ""
-"Засвідчення потрібно, щоб керувати локальними образами віртуальних машин і "
+"Потрібна автентифікація, щоб керувати локальними образами віртуальних машин і "
"контейнерів."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+#: src/resolve/org.freedesktop.resolve1.policy:22
+msgid "Register a DNS-SD service"
+msgstr "Зареєструвати службу DNS-SD"
+
+#: src/resolve/org.freedesktop.resolve1.policy:23
+#| msgid "Authentication is required to set a wall message"
+msgid "Authentication is required to register a DNS-SD service"
+msgstr "Потрібна автентифікація, щоб зареєструвати службу DNS-SD"
+
+#: src/resolve/org.freedesktop.resolve1.policy:33
+msgid "Unregister a DNS-SD service"
+msgstr "Зняти з реєстрації службу DNS-SD"
+
+#: src/resolve/org.freedesktop.resolve1.policy:34
+#| msgid "Authentication is required to set a wall message"
+msgid "Authentication is required to unregister a DNS-SD service"
+msgstr "Потрібна автентифікація, щоб зняти з реєстрації службу DNS-SD"
+
+#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
msgstr "Вказати системний час"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+#: src/timedate/org.freedesktop.timedate1.policy:23
msgid "Authentication is required to set the system time."
-msgstr "Засвідчення потрібно, щоб вказати системний час."
+msgstr "Потрібна автентифікація, щоб вказати системний час."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+#: src/timedate/org.freedesktop.timedate1.policy:33
msgid "Set system timezone"
msgstr "Вказати системний часовий пояс"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+#: src/timedate/org.freedesktop.timedate1.policy:34
msgid "Authentication is required to set the system timezone."
-msgstr "Засвідчення потрібно, щоб вказати системний часовий пояс."
+msgstr "Потрібна автентифікація, щоб вказати системний часовий пояс."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+#: src/timedate/org.freedesktop.timedate1.policy:43
msgid "Set RTC to local timezone or UTC"
msgstr "Вкажіть RTC для локального часового поясу або UTC"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+#: src/timedate/org.freedesktop.timedate1.policy:44
msgid ""
"Authentication is required to control whether the RTC stores the local or "
"UTC time."
-msgstr "Засвідчення потрібно, щоб контролювати, чи RTC зберігає час, чи UTC."
+msgstr "Потрібна автентифікація, щоб контролювати, чи RTC зберігає час, чи UTC."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+#: src/timedate/org.freedesktop.timedate1.policy:54
msgid "Turn network time synchronization on or off"
-msgstr "Увімкнути або вимкнути синхронізування через мережу"
+msgstr "Увімкнути або вимкнути синхронізування часу через мережу"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+#: src/timedate/org.freedesktop.timedate1.policy:55
msgid ""
"Authentication is required to control whether network time synchronization "
"shall be enabled."
msgstr ""
-"Засвідчення потрібно, щоб контролювати, чи синхронізування часу через мережу "
+"Потрібна автентифікація, щоб контролювати, чи синхронізування часу через мережу "
"запущено."
-#: ../src/core/dbus-unit.c:449
+#: src/core/dbus-unit.c:496
msgid "Authentication is required to start '$(unit)'."
-msgstr "Засвідчення потрібно, щоб запустити «$(unit)»."
+msgstr "Потрібна автентифікація, щоб запустити «$(unit)»."
-#: ../src/core/dbus-unit.c:450
+#: src/core/dbus-unit.c:497
msgid "Authentication is required to stop '$(unit)'."
-msgstr "Засвідчення потрібно, щоб зупинити «$(unit)»."
+msgstr "Потрібна автентифікація, щоб зупинити «$(unit)»."
-#: ../src/core/dbus-unit.c:451
+#: src/core/dbus-unit.c:498
msgid "Authentication is required to reload '$(unit)'."
-msgstr "Засвідчення потрібно, щоб перезавантажити «$(unit)»."
+msgstr "Потрібна автентифікація, щоб перезавантажити «$(unit)»."
-#: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453
+#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500
msgid "Authentication is required to restart '$(unit)'."
-msgstr "Засвідчення потрібно, щоб перезапустити «$(unit)»."
+msgstr "Потрібна автентифікація, щоб перезапустити «$(unit)»."
-#: ../src/core/dbus-unit.c:556
+#: src/core/dbus-unit.c:607
msgid "Authentication is required to kill '$(unit)'."
-msgstr "Засвідчення потрібне, щоб вбити «$(unit)»."
+msgstr "Потрібна автентифікація, щоб вбити «$(unit)»."
-#: ../src/core/dbus-unit.c:586
+#: src/core/dbus-unit.c:638
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
-msgstr "Засвідчення потрібне, щоб скинути «пошкоджений» стан з «$(unit)»."
+msgstr "Потрібна автентифікація, щоб скинути «пошкоджений» стан з «$(unit)»."
-#: ../src/core/dbus-unit.c:618
+#: src/core/dbus-unit.c:671
msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "Засвідчення потрібно, щоб вказати властивості на «$(unit)»."
+msgstr "Потрібна автентифікація, щоб вказати властивості на «$(unit)»."
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 7fbbcb1925..5236c49866 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Simplified Chinese translation for systemd.
-# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
#
# Frank Hill <hxf.prc@gmail.com>, 2014.
diff --git a/po/zh_TW.po b/po/zh_TW.po
index c2b3b08914..9c0315e884 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# Traditional Chinese translation for systemd.
-# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Jeff Huang <s8321414@gmail.com>, 2015, 2016.
msgid ""
diff --git a/presets/meson.build b/presets/meson.build
index 48aa8c9796..0b16acf59a 100644
--- a/presets/meson.build
+++ b/presets/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
install_data('90-systemd.preset',
install_dir : systempresetdir)
diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
index 0de8cf3a1a..8ddb7577c1 100644
--- a/rules/60-persistent-storage.rules
+++ b/rules/60-persistent-storage.rules
@@ -91,7 +91,7 @@ KERNEL!="sr*", IMPORT{builtin}="blkid"
# by-label/by-uuid links (filesystem metadata)
ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}"
-ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"
+ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"
# by-id (World Wide Name)
ENV{DEVTYPE}=="disk", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}"
diff --git a/rules/meson.build b/rules/meson.build
index e253b9f591..b6a32ba77e 100644
--- a/rules/meson.build
+++ b/rules/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
rules = files('''
60-block.rules
diff --git a/shell-completion/bash/bootctl b/shell-completion/bash/bootctl
index 9d7b51bcec..e24d113219 100644
--- a/shell-completion/bash/bootctl
+++ b/shell-completion/bash/bootctl
@@ -3,7 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2014 Thomas H.P. Andersen
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/busctl b/shell-completion/bash/busctl
index c357c25bc3..c5eab88caa 100644
--- a/shell-completion/bash/busctl
+++ b/shell-completion/bash/busctl
@@ -3,9 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2014 Thomas H.P. Andersen
-#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
@@ -28,20 +25,23 @@ __contains_word () {
__get_machines() {
local a b
- machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; };
+ machinectl list --no-legend --no-pager 2>/dev/null |
+ { while read a b; do echo " $a"; done; };
}
__get_busnames() {
local mode=$1
local a b
- busctl $mode list --no-legend --no-pager | { while read a b; do echo " $a"; done; };
+ busctl $mode list --no-legend --no-pager 2>/dev/null |
+ { while read a b; do echo " $a"; done; };
}
__get_objects() {
local mode=$1
local busname=$2
local a b
- busctl $mode tree --list --no-legend --no-pager $busname | { while read a b; do echo " $a"; done; };
+ busctl $mode tree --list --no-legend --no-pager $busname 2>/dev/null |
+ { while read a b; do echo " $a"; done; };
}
__get_interfaces() {
@@ -49,7 +49,8 @@ __get_interfaces() {
local busname=$2
local path=$3
local a b c
- busctl $mode introspect --list --no-legend --no-pager $busname $path | { while read a b c; do [[ "$b" == "interface" ]] && echo " $a"; done; };
+ busctl $mode introspect --list --no-legend --no-pager $busname $path 2>/dev/null |
+ { while read a b c; do [[ "$b" == "interface" ]] && echo " $a"; done; };
}
__get_members() {
@@ -60,7 +61,9 @@ __get_members() {
local type=$5
local flags=$6
local a b c d e
- busctl $mode introspect --list --no-legend --no-pager $busname $path $interface | sed -e 's/^\.//' | { while read a b c d e; do [[ "$b" == "$type" && ( -z $flags || "$e" == "$flags" ) ]] && echo " $a"; done; };
+ busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null |
+ sed -e 's/^\.//' |
+ { while read a b c d e; do [[ "$b" == "$type" && ( -z $flags || "$e" == "$flags" ) ]] && echo " $a"; done; };
}
__get_signature() {
@@ -70,7 +73,8 @@ __get_signature() {
local interface=$4
local member=$5
local a b c d
- busctl $mode introspect --list --no-legend --no-pager $busname $path $interface | sed -e 's/^\.//' | { while read a b c d; do [[ "$a" == "$member" && "$c" != '-' ]] && echo " \"$c\""; done; };
+ busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null |
+ sed -e 's/^\.//' | { while read a b c d; do [[ "$a" == "$member" && "$c" != '-' ]] && echo " \"$c\""; done; };
}
_busctl() {
diff --git a/shell-completion/bash/coredumpctl b/shell-completion/bash/coredumpctl
index bc069a7644..9bd9072def 100644
--- a/shell-completion/bash/coredumpctl
+++ b/shell-completion/bash/coredumpctl
@@ -3,7 +3,7 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
+# Copyright © 2010 Ran Benita
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/hostnamectl b/shell-completion/bash/hostnamectl
index 1b41603010..af6db81ce1 100644
--- a/shell-completion/bash/hostnamectl
+++ b/shell-completion/bash/hostnamectl
@@ -3,7 +3,7 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
+# Copyright © 2010 Ran Benita
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl
index d2b9a04706..48781ee7ce 100644
--- a/shell-completion/bash/journalctl
+++ b/shell-completion/bash/journalctl
@@ -3,7 +3,7 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
+# Copyright © 2010 Ran Benita
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
@@ -66,7 +66,7 @@ _journalctl() {
compopt -o filenames
;;
--output|-o)
- comps='short short-full short-iso short-iso-precise short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat'
+ comps='short short-full short-iso short-iso-precise short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat with-unit'
;;
--field|-F)
comps=$(journalctl --fields | sort 2>/dev/null)
diff --git a/shell-completion/bash/kernel-install b/shell-completion/bash/kernel-install
index f291d3e63a..c76bfe6e90 100644
--- a/shell-completion/bash/kernel-install
+++ b/shell-completion/bash/kernel-install
@@ -3,8 +3,7 @@
#
# This file is part of systemd.
#
-# Copyright 2013 Kay Sievers
-# Copyright 2013 Harald Hoyer
+# 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
diff --git a/shell-completion/bash/localectl b/shell-completion/bash/localectl
index f02476f733..db4eb4267f 100644
--- a/shell-completion/bash/localectl
+++ b/shell-completion/bash/localectl
@@ -3,7 +3,7 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
+# Copyright © 2010 Ran Benita
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/loginctl b/shell-completion/bash/loginctl
index f78139b266..1f5b46620c 100644
--- a/shell-completion/bash/loginctl
+++ b/shell-completion/bash/loginctl
@@ -3,7 +3,7 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
+# Copyright © 2010 Ran Benita
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/machinectl b/shell-completion/bash/machinectl
index 30cf9448e5..aa5816bbf5 100644
--- a/shell-completion/bash/machinectl
+++ b/shell-completion/bash/machinectl
@@ -3,7 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2014 Thomas H.P. Andersen
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build
index 347518cd46..e7fabe29aa 100644
--- a/shell-completion/bash/meson.build
+++ b/shell-completion/bash/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
bashcompletiondir = get_option('bashcompletiondir')
if bashcompletiondir == ''
@@ -54,6 +39,8 @@ if bashcompletiondir != 'no'
['loginctl', 'ENABLE_LOGIND'],
['machinectl', 'ENABLE_MACHINED'],
['networkctl', 'ENABLE_NETWORKD'],
+ ['portablectl', 'ENABLE_PORTABLED'],
+ ['resolvectl', 'ENABLE_RESOLVE'],
['systemd-resolve', 'ENABLE_RESOLVE'],
['timedatectl', 'ENABLE_TIMEDATED'],
]
diff --git a/shell-completion/bash/portablectl b/shell-completion/bash/portablectl
new file mode 100644
index 0000000000..22455d2c1e
--- /dev/null
+++ b/shell-completion/bash/portablectl
@@ -0,0 +1,112 @@
+# portablectl(1) completion -*- shell-script -*-
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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.
+#
+# systemd is distributed in the hope that 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/>.
+
+__contains_word () {
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
+}
+
+__get_machines() {
+ local a b
+ machinectl list --no-legend --no-pager 2>/dev/null |
+ { while read a b; do echo " $a"; done; };
+}
+
+_portablectl() {
+ local i n comps verb
+ local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+ local -A OPTS=(
+ [STANDALONE]='-q --quiet --runtime --no-reload --cat --no-pager --no-legend
+ --no-ask-password -h --help --version'
+ [ARG]='-p --profile --copy -H --host -M --machine'
+ )
+
+ local -A VERBS=(
+ [STANDALONE]='list'
+ [IMAGE]='attach detach inspect is-attached set-limit'
+ [IMAGES]='remove'
+ [IMAGE_WITH_BOOL]='read-only'
+ )
+
+ if __contains_word "$prev" ${OPTS[ARG]}; then
+ case $prev in
+ --profile|-p)
+ comps="default nonetwork strict trusted"
+ ;;
+ --copy)
+ comps="copy symlink auto"
+ ;;
+ --host|-H)
+ comps=$(compgen -A hostname)
+ ;;
+ --machine|-M)
+ comps=$( __get_machines )
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+ fi
+
+ if [[ "$cur" = -* ]]; then
+ COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
+ return 0
+ fi
+
+ for ((i=0; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ verb=${COMP_WORDS[i]}
+ break
+ fi
+ done
+
+ n=$(($COMP_CWORD - $i))
+
+ if [[ -z $verb ]]; then
+ comps=${VERBS[*]}
+ elif __contains_word "$verb" ${VERBS[STANDALONE]}; then
+ comps=''
+ elif __contains_word "$verb" ${VERBS[IMAGE]}; then
+ if [[ $n == 1 ]]; then
+ comps=$( compgen -A file -- "$cur" )
+ compopt -o filenames
+ else
+ comps=''
+ fi
+ elif __contains_word "$verb" ${VERBS[IMAGES]}; then
+ comps=$( compgen -A file -- "$cur" )
+ compopt -o filenames
+ elif __contains_word "$verb" ${VERBS[IMAGE_WITH_BOOL]}; then
+ if [[ $n == 1 ]]; then
+ comps=$( compgen -A file -- "$cur" )
+ compopt -o filenames
+ elif [[ $n == 2 ]]; then
+ comps='yes no'
+ else
+ comps=''
+ fi
+ fi
+
+ COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") )
+ return 0
+}
+
+complete -F _portablectl portablectl
diff --git a/shell-completion/bash/resolvectl b/shell-completion/bash/resolvectl
new file mode 100644
index 0000000000..8d71f8b613
--- /dev/null
+++ b/shell-completion/bash/resolvectl
@@ -0,0 +1,182 @@
+# resolvectl(1) completion -*- shell-script -*-
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of 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.
+#
+# systemd is distributed in the hope that 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/>.
+
+__contains_word () {
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
+}
+
+__get_interfaces(){
+ { cd /sys/class/net && echo *; } | \
+ while read -d' ' -r name; do
+ [[ "$name" != "lo" ]] && echo "$name"
+ done
+}
+
+_resolvectl() {
+ local i comps verb name
+ local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+ local -A OPTS=(
+ [STANDALONE]='-h --help --version --no-pager -4 -6
+ --service-address=no --service-txt=no
+ --cname=no --search=no --legend=no'
+ [ARG]='-i --interface -p --protocol -t --type -c --class --raw'
+ )
+ local -A VERBS=(
+ [DOMAIN]='query service openpgp'
+ [FAMILY]='tlsa'
+ [STATUS]='status'
+ [LINK]='revert dns domain nta'
+ [RESOLVE]='llmnr mdns'
+ [DNSSEC]='dnssec'
+ [DNSOVERTLS]='dnsovertls'
+ [STANDALONE]='statistics reset-statistics flush-caches reset-server-features'
+ )
+ local -A ARGS=(
+ [FAMILY]='tcp udp sctp'
+ [RESOLVE]='yes no resolve'
+ [DNSSEC]='yes no allow-downgrade'
+ [DNSOVERTLS]='no opportunistic'
+ )
+ local interfaces=$( __get_interfaces )
+
+ if __contains_word "$prev" ${OPTS[ARG]}; then
+ case $prev in
+ --interface|-i)
+ comps="$interfaces"
+ ;;
+ --protocol|-p|--type|-t|--class|-c)
+ comps=$( resolvectl --legend=no "$prev" help; echo help )
+ ;;
+ --raw)
+ comps="payload packet"
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+ fi
+
+ if [[ "$cur" = -* ]]; then
+ COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
+ return 0
+ fi
+
+ for ((i=0; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ verb=${COMP_WORDS[i]}
+ break
+ fi
+ done
+
+ if [[ -z $verb ]]; then
+ comps="${VERBS[*]}"
+
+ elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[DOMAIN]}; then
+ comps=''
+
+ elif __contains_word "$verb" ${VERBS[STATUS]}; then
+ comps="$interfaces"
+
+ elif __contains_word "$verb" ${VERBS[FAMILY]}; then
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${ARGS[FAMILY]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+ if [[ -z $name ]]; then
+ comps=${ARGS[FAMILY]}
+ else
+ comps=""
+ fi
+
+ elif __contains_word "$verb" ${VERBS[LINK]} ${VERBS[RESOLVE]} ${VERBS[DNSSEC]} ${VERBS[DNSOVERTLS]}; then
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" $interfaces &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+
+ if [[ -z $name ]]; then
+ comps="$interfaces"
+
+ elif __contains_word "$verb" ${VERBS[RESOLVE]}; then
+ name=
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${ARGS[RESOLVE]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+
+ if [[ -z $name ]]; then
+ comps=${ARGS[RESOLVE]}
+ else
+ comps=''
+ fi
+
+ elif __contains_word "$verb" ${VERBS[DNSSEC]}; then
+ name=
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${ARGS[DNSSEC]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+
+ if [[ -z $name ]]; then
+ comps=${ARGS[DNSSEC]}
+ else
+ comps=''
+ fi
+
+ elif __contains_word "$verb" ${VERBS[DNSOVERTLS]}; then
+ name=
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${ARGS[DNSOVERTLS]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+
+ if [[ -z $name ]]; then
+ comps=${ARGS[DNSOVERTLS]}
+ else
+ comps=''
+ fi
+
+ else
+ comps=''
+ fi
+ fi
+
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+}
+
+complete -F _resolvectl resolvectl
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index 080deeaace..ba51ae0d34 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -3,33 +3,15 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that 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/>.
+# Copyright © 2010 Ran Benita
__systemctl() {
local mode=$1; shift 1
- systemctl $mode --full --no-legend "$@" 2>/dev/null
+ systemctl $mode --full --no-legend --no-pager "$@" 2>/dev/null
}
__systemd_properties() {
- local mode=$1
- { __systemctl $mode show --all;
- @rootlibexecdir@/systemd --dump-configuration-items; } |
- while IFS='=' read -r key value; do
- [[ $value ]] && echo "$key"
- done
+ @rootlibexecdir@/systemd --dump-bus-properties
}
__contains_word () {
@@ -79,39 +61,41 @@ __filter_units_by_properties () {
done
}
-__get_all_units () { { __systemctl $1 list-unit-files; __systemctl $1 list-units --all; } \
+__get_all_units () { { __systemctl $1 list-unit-files "$2*"; __systemctl $1 list-units --all "$2*"; } \
+ | { while read -r a b; do echo " $a"; done; }; }
+__get_non_template_units() { { __systemctl $1 list-unit-files "$2*"; __systemctl $1 list-units --all "$2*"; } \
| { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }; }
-__get_template_names () { __systemctl $1 list-unit-files \
+__get_template_names () { __systemctl $1 list-unit-files "$2*" \
| { while read -r a b; do [[ $a =~ @\. ]] && echo " ${a%%@.*}@"; done; }; }
-__get_active_units () { __systemctl $1 list-units \
+__get_active_units () { __systemctl $1 list-units "$2*" \
| { while read -r a b; do echo " $a"; done; }; }
__get_startable_units () {
# find startable inactive units
__filter_units_by_properties $1 ActiveState,CanStart inactive,yes $(
- { __systemctl $1 list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient | \
+ { __systemctl $1 list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient "$2*" | \
{ while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }
- __systemctl $1 list-units --state inactive,failed | \
+ __systemctl $1 list-units --state inactive,failed "$2*" | \
{ while read -r a b c; do [[ $b == "loaded" ]] && echo " $a"; done; }
} | sort -u )
}
__get_restartable_units () {
# filter out masked and not-found
__filter_units_by_property $1 CanStart yes $(
- __systemctl $1 list-unit-files --state enabled,disabled,static | \
+ __systemctl $1 list-unit-files --state enabled,disabled,static "$2*" | \
{ while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }
- __systemctl $1 list-units | \
+ __systemctl $1 list-units "$2*" | \
{ while read -r a b; do echo " $a"; done; } )
}
-__get_failed_units () { __systemctl $1 list-units \
+__get_failed_units () { __systemctl $1 list-units "$2*" \
| { while read -r a b c d; do [[ $c == "failed" ]] && echo " $a"; done; }; }
-__get_enabled_units () { __systemctl $1 list-unit-files \
+__get_enabled_units () { __systemctl $1 list-unit-files "$2*" \
| { while read -r a b c ; do [[ $b == "enabled" ]] && echo " $a"; done; }; }
-__get_disabled_units () { __systemctl $1 list-unit-files \
+__get_disabled_units () { __systemctl $1 list-unit-files "$2*" \
| { while read -r a b c ; do [[ $b == "disabled" ]] && echo " $a"; done; }; }
-__get_masked_units () { __systemctl $1 list-unit-files \
+__get_masked_units () { __systemctl $1 list-unit-files "$2*" \
| { while read -r a b c ; do [[ $b == "masked" ]] && echo " $a"; done; }; }
-__get_all_unit_files () { { __systemctl $1 list-unit-files; } | { while read -r a b; do echo " $a"; done; }; }
+__get_all_unit_files () { { __systemctl $1 list-unit-files "$2*"; } | { while read -r a b; do echo " $a"; done; }; }
__get_machines() {
local a b
@@ -167,7 +151,7 @@ _systemctl () {
comps=$(compgen -A hostname)
;;
--property|-p)
- comps=$(__systemd_properties $mode)
+ comps=$(__systemd_properties)
;;
--preset-mode)
comps='full enable-only disable-only'
@@ -190,7 +174,8 @@ _systemctl () {
fi
local -A VERBS=(
- [ALL_UNITS]='is-active is-failed is-enabled status show cat mask preset help list-dependencies edit set-property revert'
+ [ALL_UNITS]='cat mask'
+ [NONTEMPLATE_UNITS]='is-active is-failed is-enabled status show preset help list-dependencies edit set-property revert'
[ENABLED_UNITS]='disable'
[DISABLED_UNITS]='enable'
[REENABLABLE_UNITS]='reenable'
@@ -205,8 +190,9 @@ _systemctl () {
[JOBS]='cancel'
[ENVS]='set-environment unset-environment import-environment'
[STANDALONE]='daemon-reexec daemon-reload default
- emergency exit halt hibernate hybrid-sleep kexec list-jobs
- list-sockets list-timers list-units list-unit-files poweroff
+ emergency exit halt hibernate hybrid-sleep
+ suspend-then-hibernate kexec list-jobs list-sockets
+ list-timers list-units list-unit-files poweroff
reboot rescue show-environment suspend get-default
is-system-running preset-all'
[FILE]='link switch-root'
@@ -226,64 +212,66 @@ _systemctl () {
comps="${VERBS[*]}"
elif __contains_word "$verb" ${VERBS[ALL_UNITS]}; then
- comps=$( __get_all_units $mode )
+ comps=$( __get_all_units $mode "$cur" )
+ compopt -o filenames
+
+ elif __contains_word "$verb" ${VERBS[NONTEMPLATE_UNITS]}; then
+ comps=$( __get_non_template_units $mode "$cur" )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[ENABLED_UNITS]}; then
- comps=$( __get_enabled_units $mode )
+ comps=$( __get_enabled_units $mode "$cur" )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[DISABLED_UNITS]}; then
- comps=$( __get_disabled_units $mode;
- __get_template_names $mode)
+ comps=$( __get_disabled_units $mode "$cur";
+ __get_template_names $mode "$cur")
compopt -o filenames
elif __contains_word "$verb" ${VERBS[REENABLABLE_UNITS]}; then
- comps=$( __get_disabled_units $mode;
- __get_enabled_units $mode;
- __get_template_names $mode)
+ comps=$( __get_disabled_units $mode "$cur";
+ __get_enabled_units $mode "$cur";
+ __get_template_names $mode "$cur")
compopt -o filenames
elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then
- comps=$( __get_startable_units $mode;
- __get_template_names $mode)
+ comps=$( __get_startable_units $mode "$cur" )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[RESTARTABLE_UNITS]}; then
- comps=$( __get_restartable_units $mode;
- __get_template_names $mode)
+ comps=$( __get_restartable_units $mode "$cur" )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[STOPPABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode CanStop yes \
- $( __get_active_units $mode ) )
+ $( __get_active_units $mode "$cur" ) )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[RELOADABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode CanReload yes \
- $( __get_active_units $mode ) )
+ $( __get_active_units $mode "$cur" ) )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[ISOLATABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode AllowIsolate yes \
- $( __get_all_units $mode ) )
+ $( __get_all_units $mode "$cur" ) )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[FAILED_UNITS]}; then
- comps=$( __get_failed_units $mode )
+ comps=$( __get_failed_units $mode "$cur" )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[MASKED_UNITS]}; then
- comps=$( __get_masked_units $mode )
+ comps=$( __get_masked_units $mode "$cur" )
compopt -o filenames
elif __contains_word "$verb" ${VERBS[TARGET_AND_UNITS]}; then
if __contains_word "$prev" ${VERBS[TARGET_AND_UNITS]} \
|| __contains_word "$prev" ${OPTS[STANDALONE]}; then
- comps=$( __systemctl $mode list-unit-files --type target --all \
+ comps=$( __systemctl $mode list-unit-files --type target --all "$cur*" \
| { while read -r a b; do echo " $a"; done; } )
else
- comps=$( __get_all_unit_files $mode )
+ comps=$( __get_all_unit_files $mode "$cur" )
fi
compopt -o filenames
@@ -303,7 +291,7 @@ _systemctl () {
compopt -o filenames
elif __contains_word "$verb" ${VERBS[TARGETS]}; then
- comps=$( __systemctl $mode list-unit-files --type target --full --all \
+ comps=$( __systemctl $mode list-unit-files --type target --full --all "$cur*" \
| { while read -r a b; do echo " $a"; done; } )
fi
diff --git a/shell-completion/bash/systemd-analyze b/shell-completion/bash/systemd-analyze
index a66ddccb02..21d0fcf1b8 100644
--- a/shell-completion/bash/systemd-analyze
+++ b/shell-completion/bash/systemd-analyze
@@ -3,8 +3,8 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
-# Copyright 2013 Harald Hoyer
+# Copyright © 2010 Ran Benita
+# 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
@@ -38,7 +38,7 @@ _systemd_analyze() {
local -A OPTS=(
[STANDALONE]='-h --help --version --system --user --global --order --require --no-pager
--man=no --generators=yes'
- [ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern'
+ [ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern --root'
)
local -A VERBS=(
@@ -50,8 +50,15 @@ _systemd_analyze() {
[VERIFY]='verify'
[SECCOMP_FILTER]='syscall-filter'
[SERVICE_WATCHDOGS]='service-watchdogs'
+ [CAT_CONFIG]='cat-config'
)
+ local CONFIGS='systemd/bootchart.conf systemd/coredump.conf systemd/journald.conf
+ systemd/journal-remote.conf systemd/journal-upload.conf systemd/logind.conf
+ systemd/resolved.conf systemd/networkd.conf systemd/resolved.conf
+ systemd/sleep.conf systemd/system.conf systemd/timedated.conf
+ systemd/timesyncd.conf systemd/user.conf udev/udev.conf'
+
_init_completion || return
for ((i=0; i < COMP_CWORD; i++)); do
@@ -85,12 +92,12 @@ _systemd_analyze() {
elif __contains_word "$verb" ${VERBS[STANDALONE]}; then
if [[ $cur = -* ]]; then
- comps='--help --version --system --user --global'
+ comps='--help --version --system --user --global --no-pager'
fi
elif __contains_word "$verb" ${VERBS[CRITICAL_CHAIN]}; then
if [[ $cur = -* ]]; then
- comps='--help --version --system --user --fuzz'
+ comps='--help --version --system --user --fuzz --no-pager'
fi
elif __contains_word "$verb" ${VERBS[DOT]}; then
@@ -114,7 +121,7 @@ _systemd_analyze() {
elif __contains_word "$verb" ${VERBS[SECCOMP_FILTER]}; then
if [[ $cur = -* ]]; then
- comps='--help --version'
+ comps='--help --version --no-pager'
fi
elif __contains_word "$verb" ${VERBS[VERIFY]}; then
@@ -132,6 +139,16 @@ _systemd_analyze() {
comps='on off'
fi
+ elif __contains_word "$verb" ${VERBS[CAT_CONFIG]}; then
+ if [[ $cur = -* ]]; then
+ comps='--help --version --root --no-pager'
+ elif [[ -z $cur ]]; then
+ comps="$CONFIGS"
+ compopt -o filenames
+ else
+ comps="$CONFIGS $( compgen -A file -- "$cur" )"
+ compopt -o filenames
+ fi
fi
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
diff --git a/shell-completion/bash/systemd-cat b/shell-completion/bash/systemd-cat
index 20ff672059..c75871c482 100644
--- a/shell-completion/bash/systemd-cat
+++ b/shell-completion/bash/systemd-cat
@@ -3,7 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2014 Thomas H.P. Andersen
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/systemd-cgls b/shell-completion/bash/systemd-cgls
index 34c7b9e67f..1e2074a8cb 100644
--- a/shell-completion/bash/systemd-cgls
+++ b/shell-completion/bash/systemd-cgls
@@ -3,7 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2014 Thomas H.P. Andersen
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/systemd-cgtop b/shell-completion/bash/systemd-cgtop
index 7a1b4acc7c..8bd83ca442 100644
--- a/shell-completion/bash/systemd-cgtop
+++ b/shell-completion/bash/systemd-cgtop
@@ -3,7 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2014 Thomas H.P. Andersen
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/systemd-delta b/shell-completion/bash/systemd-delta
index d3933437b3..29f528cc7a 100644
--- a/shell-completion/bash/systemd-delta
+++ b/shell-completion/bash/systemd-delta
@@ -3,7 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2014 Thomas H.P. Andersen
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/systemd-detect-virt b/shell-completion/bash/systemd-detect-virt
index 5fab7cb12e..cdb516da64 100644
--- a/shell-completion/bash/systemd-detect-virt
+++ b/shell-completion/bash/systemd-detect-virt
@@ -3,7 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2014 Thomas H.P. Andersen
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/systemd-nspawn b/shell-completion/bash/systemd-nspawn
index 660972d9f1..2ff39b65d7 100644
--- a/shell-completion/bash/systemd-nspawn
+++ b/shell-completion/bash/systemd-nspawn
@@ -3,7 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2014 Thomas H.P. Andersen
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/bash/systemd-resolve b/shell-completion/bash/systemd-resolve
index ecd1ebad54..86b8db2cf8 100644
--- a/shell-completion/bash/systemd-resolve
+++ b/shell-completion/bash/systemd-resolve
@@ -3,8 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2016 Zbigniew Jędrzejewski-Szmek
-#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
@@ -65,6 +63,9 @@ _systemd-resolve() {
--set-dnssec)
comps="yes no allow-downgrade"
;;
+ --set-dnsovertls)
+ comps="no opportunistic"
+ ;;
esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0
diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run
index b9114fc1b5..d317466b26 100644
--- a/shell-completion/bash/systemd-run
+++ b/shell-completion/bash/systemd-run
@@ -3,8 +3,6 @@
#
# This file is part of systemd.
#
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
diff --git a/shell-completion/bash/timedatectl b/shell-completion/bash/timedatectl
index 13b99f22ba..b2dd1a88c4 100644
--- a/shell-completion/bash/timedatectl
+++ b/shell-completion/bash/timedatectl
@@ -3,7 +3,7 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
+# Copyright © 2010 Ran Benita
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
@@ -34,7 +34,8 @@ _timedatectl() {
local i verb comps
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local OPTS='-h --help --version --adjust-system-clock --no-pager
- --no-ask-password -H --host -M --machine'
+ --no-ask-password -H --host -M --machine --monitor
+ -p --property -a --all --value'
if __contains_word "$prev" $OPTS; then
case $prev in
@@ -56,7 +57,7 @@ _timedatectl() {
local -A VERBS=(
[BOOLEAN]='set-local-rtc set-ntp'
- [STANDALONE]='status list-timezones'
+ [STANDALONE]='status show list-timezones timesync-status show-timesync'
[TIMEZONES]='set-timezone'
[TIME]='set-time'
)
diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm
index 744a38826b..e5c11bf43c 100644
--- a/shell-completion/bash/udevadm
+++ b/shell-completion/bash/udevadm
@@ -3,7 +3,7 @@
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
+# Copyright © 2010 Ran Benita
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
diff --git a/shell-completion/zsh/_busctl b/shell-completion/zsh/_busctl
index 883ace47af..801ed48010 100644
--- a/shell-completion/zsh/_busctl
+++ b/shell-completion/zsh/_busctl
@@ -5,8 +5,6 @@
#
# This file is part of systemd.
#
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
diff --git a/shell-completion/zsh/_sd_outputmodes b/shell-completion/zsh/_sd_outputmodes
index 3b8850b3f0..70ff7233af 100644
--- a/shell-completion/zsh/_sd_outputmodes
+++ b/shell-completion/zsh/_sd_outputmodes
@@ -2,5 +2,5 @@
# SPDX-License-Identifier: LGPL-2.1+
local -a _output_opts
-_output_opts=(short short-full short-iso short-iso-precise short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat)
+_output_opts=(short short-full short-iso short-iso-precise short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat with-unit)
_describe -t output 'output mode' _output_opts || compadd "$@"
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index a3df9a0457..9f576ed77d 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -18,6 +18,7 @@
"force-reload:Reload one or more units if possible, otherwise restart if active"
"hibernate:Hibernate the system"
"hybrid-sleep:Hibernate and suspend the system"
+ "suspend-then-hibernate:Suspend the system for a period of time, and then hibernate it"
"try-reload-or-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"
@@ -105,7 +106,7 @@ _systemctl_all_units()
if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS$_sys_service_mgr ) ||
! _retrieve_cache SYS_ALL_UNITS$_sys_service_mgr;
then
- _sys_all_units=( ${${(f)"$(__systemctl list-units --all)"}%% *} )
+ _sys_all_units=( ${${(f)"$(__systemctl list-units --all "$PREFIX*" )"}%% *} )
_store_cache SYS_ALL_UNITS$_sys_service_mgr _sys_all_units
fi
}
@@ -118,7 +119,7 @@ _systemctl_really_all_units()
if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS$_sys_service_mgr ) ||
! _retrieve_cache SYS_REALLY_ALL_UNITS$_sys_service_mgr;
then
- all_unit_files=( ${${(f)"$(__systemctl list-unit-files)"}%% *} )
+ all_unit_files=( ${${(f)"$(__systemctl list-unit-files "$PREFIX*" )"}%% *} )
_systemctl_all_units
really_all_units=($_sys_all_units $all_unit_files)
_sys_really_all_units=(${(u)really_all_units})
@@ -134,33 +135,38 @@ _filter_units_by_property() {
echo -E - "${(@g:o:)${(k@)props[(Re)$property=$value]}#Id=}"
}
-_systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files "*$PREFIX*$SUFFIX*" )"}##*@.[^[:space:]]##}%%@.*}\@ }
+_systemctl_get_non_template_names() { echo -E - ${^${(R)${(f)"$(
+ __systemctl $mode list-unit-files "$PREFIX*"
+ __systemctl $mode list-units --all "$PREFIX*"
+ )"}:#*@.*}%%[[:space:]]*} }
+_systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files "$PREFIX*" )"}##*@.[^[:space:]]##}%%@.*}\@ }
-_systemctl_active_units() {_sys_active_units=( ${${(f)"$(__systemctl list-units "*$PREFIX*$SUFFIX*" )"}%% *} )}
+
+_systemctl_active_units() {_sys_active_units=( ${${(f)"$(__systemctl list-units "$PREFIX*" )"}%% *} )}
_systemctl_startable_units(){
_sys_startable_units=( $( _filter_units_by_property ActiveState inactive $(
_filter_units_by_property CanStart yes ${${${(f)"$(
- __systemctl $mode list-unit-files --state enabled,disabled,static "*$PREFIX*$SUFFIX*"
- __systemctl $mode list-units --state inactive,failed "*$PREFIX*$SUFFIX*"
+ __systemctl $mode list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient "$PREFIX*"
+ __systemctl $mode list-units --state inactive,failed "$PREFIX*"
)"}:#*@.*}%%[[:space:]]*}
)) )
}
_systemctl_restartable_units(){
_sys_restartable_units=( $( _filter_units_by_property CanStart yes ${${${(f)"$(
- __systemctl $mode list-unit-files --state enabled,disabled,static "*$PREFIX*$SUFFIX*"
- __systemctl $mode list-units "*$PREFIX*$SUFFIX*"
+ __systemctl $mode list-unit-files --state enabled,disabled,static "$PREFIX*"
+ __systemctl $mode list-units "$PREFIX*"
)"}:#*@.*}%%[[:space:]]*} ) )
}
-_systemctl_failed_units() {_sys_failed_units=( ${${(f)"$(__systemctl list-units --state=failed "*$PREFIX*$SUFFIX*" )"}%% *} ) }
-_systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files "*$PREFIX*$SUFFIX*" ) ) }
+_systemctl_failed_units() {_sys_failed_units=( ${${(f)"$(__systemctl list-units --state=failed "$PREFIX*" )"}%% *} ) }
+_systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files "$PREFIX*" ) ) }
local fun
# Completion functions for ALL_UNITS
-for fun in is-active is-failed is-enabled status show cat mask preset help list-dependencies edit revert add-wants add-requires ; do
+for fun in cat mask ; do
(( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
{
_systemctl_really_all_units
@@ -169,6 +175,15 @@ for fun in is-active is-failed is-enabled status show cat mask preset help list-
}
done
+# Completion functions for NONTEMPLATE_UNITS
+for fun in is-active is-failed is-enabled status show preset help list-dependencies edit revert add-wants add-requires ; do
+ (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+ {
+ _wanted systemd-units expl unit \
+ compadd "$@" - $(_systemctl_get_non_template_names)
+ }
+done
+
# Completion functions for ENABLED_UNITS
(( $+functions[_systemctl_disable] )) || _systemctl_disable()
{
@@ -205,7 +220,7 @@ done
{
local _sys_startable_units; _systemctl_startable_units
_wanted systemd-units expl 'startable unit' \
- compadd "$@" - ${_sys_startable_units[*]} $(_systemctl_get_template_names)
+ compadd "$@" - ${_sys_startable_units[*]}
}
# Completion functions for STOPPABLE_UNITS
@@ -245,7 +260,7 @@ for fun in restart reload-or-restart ; do
{
local _sys_restartable_units; _systemctl_restartable_units
_wanted systemd-units expl 'restartable unit' \
- compadd "$@" - ${_sys_restartable_units[*]} $(_systemctl_get_template_names)
+ compadd "$@" - ${_sys_restartable_units[*]}
}
done
@@ -269,7 +284,7 @@ done
(( $+functions[_systemctl_set-default] )) || _systemctl_set-default()
{
_wanted systemd-targets expl target \
- compadd "$@" - ${${(f)"$(__systemctl list-unit-files --type target --all)"}%% *} ||
+ compadd "$@" - ${${(f)"$(__systemctl list-unit-files --type target --all "$PREFIX*" )"}%% *} ||
_message "no targets found"
}
@@ -336,9 +351,7 @@ _unit_properties() {
if ( [[ ${+_sys_all_properties} -eq 0 ]] || _cache_invalid SYS_ALL_PROPERTIES$_sys_service_mgr ) ||
! _retrieve_cache SYS_ALL_PROPERTIES$_sys_service_mgr;
then
- _sys_all_properties=( ${${(M)${(f)"$(__systemctl show --all;
- @rootlibexecdir@/systemd --dump-configuration-items)"}##[[:alnum:]]##=*}%%=*}
- )
+ _sys_all_properties=( ${${(M)${(f)"$(@rootlibexecdir@/systemd --dump-bus-properties)"}}} )
_store_cache SYS_ALL_PROPERTIES$_sys_service_mgr _sys_all_properties
fi
_values -s , "${_sys_all_properties[@]}"
diff --git a/shell-completion/zsh/_systemd-resolve b/shell-completion/zsh/_systemd-resolve
index eb7606af30..b54d22f816 100644
--- a/shell-completion/zsh/_systemd-resolve
+++ b/shell-completion/zsh/_systemd-resolve
@@ -4,8 +4,6 @@
#
# This file is part of systemd.
#
-# Copyright 2016 Zbigniew Jędrzejewski-Szmek
-#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
diff --git a/shell-completion/zsh/meson.build b/shell-completion/zsh/meson.build
index cf3c556f13..7fc9fcfc71 100644
--- a/shell-completion/zsh/meson.build
+++ b/shell-completion/zsh/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
zshcompletiondir = get_option('zshcompletiondir')
if zshcompletiondir == ''
diff --git a/src/ac-power/ac-power.c b/src/ac-power/ac-power.c
index 6d3172d5c1..7ca72ef5f5 100644
--- a/src/ac-power/ac-power.c
+++ b/src/ac-power/ac-power.c
@@ -1,24 +1,67 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
- Copyright 2010 Lennart Poettering
+#include <getopt.h>
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
+#include "util.h"
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+static bool arg_verbose = false;
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+static void help(void) {
+ printf("%s\n\n"
+ "Report whether we are connected to an external power source.\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " -v --verbose Show state as text\n"
+ , program_invocation_short_name);
+}
-#include "util.h"
+static int parse_argv(int argc, char *argv[]) {
+
+ enum {
+ ARG_VERSION = 0x100,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "verbose", no_argument, NULL, 'v' },
+ {}
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "hv", options, NULL)) >= 0)
+
+ switch (c) {
+
+ case 'h':
+ help();
+ return 0;
+
+ case ARG_VERSION:
+ return version();
+
+ case 'v':
+ arg_verbose = true;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
+ }
+
+ if (optind < argc) {
+ log_error("%s takes no arguments.", program_invocation_short_name);
+ return -EINVAL;
+ }
+
+ return 1;
+}
int main(int argc, char *argv[]) {
int r;
@@ -26,11 +69,22 @@ int main(int argc, char *argv[]) {
/* This is mostly intended to be used for scripts which want
* to detect whether AC power is plugged in or not. */
+ log_parse_environment();
+ log_open();
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ goto finish;
+
r = on_ac_power();
if (r < 0) {
log_error_errno(r, "Failed to read AC status: %m");
- return EXIT_FAILURE;
+ goto finish;
}
- return r != 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ if (arg_verbose)
+ puts(yes_no(r));
+
+finish:
+ return r < 0 ? EXIT_FAILURE : !r;
}
diff --git a/src/activate/activate.c b/src/activate/activate.c
index e605d50ce0..45386a38f4 100644
--- a/src/activate/activate.c
+++ b/src/activate/activate.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
#include <sys/epoll.h>
@@ -48,16 +30,14 @@ static bool arg_inetd = false;
static int add_epoll(int epoll_fd, int fd) {
struct epoll_event ev = {
- .events = EPOLLIN
+ .events = EPOLLIN,
+ .data.fd = fd,
};
- int r;
assert(epoll_fd >= 0);
assert(fd >= 0);
- ev.data.fd = fd;
- r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
- if (r < 0)
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
return log_error_errno(errno, "Failed to add event on epoll fd:%d for fd:%d: %m", epoll_fd, fd);
return 0;
@@ -131,11 +111,11 @@ static int open_sockets(int *epoll_fd, bool accept) {
return count;
}
-static int exec_process(const char* name, char **argv, char **env, int start_fd, int n_fds) {
+static int exec_process(const char* name, char **argv, char **env, int start_fd, size_t n_fds) {
_cleanup_strv_free_ char **envp = NULL;
_cleanup_free_ char *joined = NULL;
- unsigned n_env = 0, length;
+ size_t n_env = 0, length;
const char *tocopy;
char **s;
int r;
@@ -207,15 +187,14 @@ static int exec_process(const char* name, char **argv, char **env, int start_fd,
if (start_fd != SD_LISTEN_FDS_START) {
assert(n_fds == 1);
- r = dup2(start_fd, SD_LISTEN_FDS_START);
- if (r < 0)
+ if (dup2(start_fd, SD_LISTEN_FDS_START) < 0)
return log_error_errno(errno, "Failed to dup connection: %m");
safe_close(start_fd);
start_fd = SD_LISTEN_FDS_START;
}
- if (asprintf((char**)(envp + n_env++), "LISTEN_FDS=%i", n_fds) < 0)
+ if (asprintf((char**)(envp + n_env++), "LISTEN_FDS=%zu", n_fds) < 0)
return log_oom();
if (asprintf((char**)(envp + n_env++), "LISTEN_PID=" PID_FMT, getpid_cached()) < 0)
@@ -225,18 +204,18 @@ static int exec_process(const char* name, char **argv, char **env, int start_fd,
_cleanup_free_ char *names = NULL;
size_t len;
char *e;
- int i;
len = strv_length(arg_fdnames);
- if (len == 1)
+ if (len == 1) {
+ size_t i;
+
for (i = 1; i < n_fds; i++) {
r = strv_extend(&arg_fdnames, arg_fdnames[0]);
if (r < 0)
return log_error_errno(r, "Failed to extend strv: %m");
}
- else if (len != (unsigned) n_fds)
- log_warning("The number of fd names is different than number of fds: %zu vs %d",
- len, n_fds);
+ } else if (len != n_fds)
+ log_warning("The number of fd names is different than number of fds: %zu vs %zu", len, n_fds);
names = strv_join(arg_fdnames, ":");
if (!names)
@@ -325,10 +304,7 @@ static int install_chld_handler(void) {
.sa_handler = sigchld_hdl,
};
- int r;
-
- r = sigaction(SIGCHLD, &act, 0);
- if (r < 0)
+ if (sigaction(SIGCHLD, &act, 0) < 0)
return log_error_errno(errno, "Failed to install SIGCHLD handler: %m");
return 0;
@@ -503,8 +479,7 @@ int main(int argc, char **argv, char **envp) {
for (;;) {
struct epoll_event event;
- r = epoll_wait(epoll_fd, &event, 1, -1);
- if (r < 0) {
+ if (epoll_wait(epoll_fd, &event, 1, -1) < 0) {
if (errno == EINTR)
continue;
@@ -521,7 +496,7 @@ int main(int argc, char **argv, char **envp) {
break;
}
- exec_process(argv[optind], argv + optind, envp, SD_LISTEN_FDS_START, n);
+ exec_process(argv[optind], argv + optind, envp, SD_LISTEN_FDS_START, (size_t) n);
return EXIT_SUCCESS;
}
diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c
index f475b6598c..ed369532d4 100644
--- a/src/analyze/analyze-verify.c
+++ b/src/analyze/analyze-verify.c
@@ -1,26 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdlib.h>
#include "alloc-util.h"
+#include "all-units.h"
#include "analyze-verify.h"
#include "bus-error.h"
#include "bus-util.h"
@@ -125,10 +108,8 @@ static int verify_socket(Unit *u) {
/* This makes sure instance is created if necessary. */
r = socket_instantiate_service(SOCKET(u));
- if (r < 0) {
- log_unit_error_errno(u, r, "Socket cannot be started, failed to create instance: %m");
- return r;
- }
+ if (r < 0)
+ return log_unit_error_errno(u, r, "Socket cannot be started, failed to create instance: %m");
/* This checks both type of sockets */
if (UNIT_ISSET(SOCKET(u)->service)) {
@@ -244,18 +225,15 @@ static int verify_unit(Unit *u, bool check_man) {
}
int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators) {
- _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *var = NULL;
- Manager *m = NULL;
- FILE *serial = NULL;
- FDSet *fdset = NULL;
- char **filename;
- int r = 0, k;
+ const uint8_t flags = MANAGER_TEST_RUN_BASIC |
+ MANAGER_TEST_RUN_ENV_GENERATORS |
+ run_generators * MANAGER_TEST_RUN_GENERATORS;
+ _cleanup_(manager_freep) Manager *m = NULL;
Unit *units[strv_length(filenames)];
- int i, count = 0;
- const uint8_t flags = MANAGER_TEST_RUN_ENV_GENERATORS |
- run_generators * MANAGER_TEST_RUN_GENERATORS;
+ _cleanup_free_ char *var = NULL;
+ int r = 0, k, i, count = 0;
+ char **filename;
if (strv_isempty(filenames))
return 0;
@@ -273,11 +251,9 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
log_debug("Starting manager...");
- r = manager_startup(m, serial, fdset);
- if (r < 0) {
- log_error_errno(r, "Failed to start manager: %m");
- goto finish;
- }
+ r = manager_startup(m, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to start manager: %m");
manager_clear_jobs(m);
@@ -296,12 +272,10 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
continue;
}
- k = manager_load_unit(m, NULL, prepared, &err, &units[count]);
- if (k < 0) {
- log_error_errno(k, "Failed to load %s: %m", *filename);
- if (r == 0)
- r = k;
- } else
+ k = manager_load_startable_unit_or_warn(m, NULL, prepared, &units[count]);
+ if (k < 0 && r == 0)
+ r = k;
+ else
count++;
}
@@ -311,8 +285,5 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
r = k;
}
-finish:
- manager_free(m);
-
return r;
}
diff --git a/src/analyze/analyze-verify.h b/src/analyze/analyze-verify.h
index a895130508..f6b7f54961 100644
--- a/src/analyze/analyze-verify.h
+++ b/src/analyze/analyze-verify.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "path-lookup.h"
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index ab1895d1c3..9f239c8eeb 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010-2013 Lennart Poettering
- Copyright 2013 Simon Peeters
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Simon Peeters
***/
#include <getopt.h>
@@ -32,12 +16,17 @@
#include "bus-unit-util.h"
#include "bus-util.h"
#include "calendarspec.h"
+#include "def.h"
+#include "conf-files.h"
+#include "copy.h"
+#include "fd-util.h"
#include "glob-util.h"
#include "hashmap.h"
#include "locale-util.h"
#include "log.h"
#include "pager.h"
#include "parse-util.h"
+#include "path-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
@@ -83,6 +72,7 @@ static const char *arg_host = NULL;
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
static bool arg_man = true;
static bool arg_generators = false;
+static const char *arg_root = NULL;
struct boot_times {
usec_t firmware_time;
@@ -113,6 +103,7 @@ struct boot_times {
};
struct unit_times {
+ bool has_data;
char *name;
usec_t activating;
usec_t activated;
@@ -131,13 +122,19 @@ struct host_info {
char *architecture;
};
-static int acquire_bus(bool need_full_bus, sd_bus **bus) {
+static int acquire_bus(sd_bus **bus, bool *use_full_bus) {
bool user = arg_scope != UNIT_FILE_SYSTEM;
+ int r;
+
+ if (use_full_bus && *use_full_bus) {
+ r = bus_connect_transport(arg_transport, arg_host, user, bus);
+ if (IN_SET(r, 0, -EHOSTDOWN))
+ return r;
- if (need_full_bus)
- return bus_connect_transport(arg_transport, arg_host, user, bus);
- else
- return bus_connect_transport_systemd(arg_transport, arg_host, user, bus);
+ *use_full_bus = false;
+ }
+
+ return bus_connect_transport_systemd(arg_transport, arg_host, user, bus);
}
static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
@@ -202,15 +199,16 @@ static int compare_unit_start(const void *a, const void *b) {
((struct unit_times *)b)->activating);
}
-static void free_unit_times(struct unit_times *t, unsigned n) {
+static void unit_times_free(struct unit_times *t) {
struct unit_times *p;
- for (p = t; p < t + n; p++)
+ for (p = t; p->has_data; p++)
free(p->name);
-
free(t);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct unit_times *, unit_times_free);
+
static void subtract_timestamp(usec_t *a, usec_t b) {
assert(a);
@@ -292,7 +290,11 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
return -EIO;
if (times.finish_time <= 0) {
- log_error("Bootup is not yet finished. Please try again later.");
+ log_error("Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n"
+ "Please try again later.\n"
+ "Hint: Use 'systemctl%s list-jobs' to see active jobs",
+ times.finish_time,
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
return -EINPROGRESS;
}
@@ -350,13 +352,13 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r, c = 0;
struct boot_times *boot_times = NULL;
- struct unit_times *unit_times = NULL;
+ _cleanup_(unit_times_freep) struct unit_times *unit_times = NULL;
size_t size = 0;
UnitInfo u;
r = acquire_boot_times(bus, &boot_times);
if (r < 0)
- goto fail;
+ return r;
r = sd_bus_call_method(
bus,
@@ -368,24 +370,21 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
NULL);
if (r < 0) {
log_error("Failed to list units: %s", bus_error_message(&error, -r));
- goto fail;
+ return r;
}
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
- if (r < 0) {
- bus_log_parse_error(r);
- goto fail;
- }
+ if (r < 0)
+ return bus_log_parse_error(r);
while ((r = bus_parse_unit_info(reply, &u)) > 0) {
struct unit_times *t;
- if (!GREEDY_REALLOC(unit_times, size, c+1)) {
- r = log_oom();
- goto fail;
- }
+ if (!GREEDY_REALLOC(unit_times, size, c+2))
+ return log_oom();
- t = unit_times+c;
+ unit_times[c+1].has_data = false;
+ t = &unit_times[c];
t->name = NULL;
assert_cc(sizeof(usec_t) == sizeof(uint64_t));
@@ -405,10 +404,8 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
bus_get_uint64_property(bus, u.unit_path,
"org.freedesktop.systemd1.Unit",
"InactiveEnterTimestampMonotonic",
- &t->deactivated) < 0) {
- r = -EIO;
- goto fail;
- }
+ &t->deactivated) < 0)
+ return -EIO;
subtract_timestamp(&t->activating, boot_times->reverse_offset);
subtract_timestamp(&t->activated, boot_times->reverse_offset);
@@ -426,23 +423,17 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
continue;
t->name = strdup(u.id);
- if (!t->name) {
- r = log_oom();
- goto fail;
- }
+ if (!t->name)
+ return log_oom();
+
+ t->has_data = true;
c++;
}
- if (r < 0) {
- bus_log_parse_error(r);
- goto fail;
- }
+ if (r < 0)
+ return bus_log_parse_error(r);
- *out = unit_times;
+ *out = TAKE_PTR(unit_times);
return c;
-
-fail:
- free_unit_times(unit_times, (unsigned) c);
- return r;
}
static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
@@ -473,7 +464,9 @@ static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
"org.freedesktop.hostname1",
"/org/freedesktop/hostname1",
hostname_map,
+ BUS_MAP_STRDUP,
&error,
+ NULL,
host);
if (r < 0)
log_debug_errno(r, "Failed to get host information from systemd-hostnamed: %s", bus_error_message(&error, r));
@@ -482,13 +475,14 @@ static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
manager_map,
+ BUS_MAP_STRDUP,
&error,
+ NULL,
host);
if (r < 0)
return log_error_errno(r, "Failed to get host information from systemd: %s", bus_error_message(&error, r));
- *hi = host;
- host = NULL;
+ *hi = TAKE_PTR(host);
return 0;
}
@@ -560,7 +554,6 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) {
else if (!unit_id)
size = strpcpyf(&ptr, size, "\ncould not find default.target");
-
ptr = strdup(buf);
if (!ptr)
return log_oom();
@@ -595,14 +588,15 @@ static void svg_graph_box(double height, double begin, double end) {
static int analyze_plot(int argc, char *argv[], void *userdata) {
_cleanup_(free_host_infop) struct host_info *host = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- struct unit_times *times;
+ _cleanup_(unit_times_freep) struct unit_times *times = NULL;
struct boot_times *boot;
int n, m = 1, y = 0, r;
+ bool use_full_bus = true;
double width;
_cleanup_free_ char *pretty_times = NULL;
struct unit_times *u;
- r = acquire_bus(true, &bus);
+ r = acquire_bus(&bus, &use_full_bus);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -614,9 +608,11 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
if (n < 0)
return n;
- n = acquire_host_info(bus, &host);
- if (n < 0)
- return n;
+ if (use_full_bus) {
+ n = acquire_host_info(bus, &host);
+ if (n < 0)
+ return n;
+ }
n = acquire_time_data(bus, &times);
if (n <= 0)
@@ -640,7 +636,7 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
if (boot->kernel_time > 0)
m++;
- for (u = times; u < times + n; u++) {
+ for (u = times; u->has_data; u++) {
double text_start, text_width;
if (u->activating < boot->userspace_time ||
@@ -714,14 +710,15 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
svg("<rect class=\"background\" width=\"100%%\" height=\"100%%\" />\n");
svg("<text x=\"20\" y=\"50\">%s</text>", pretty_times);
- svg("<text x=\"20\" y=\"30\">%s %s (%s %s %s) %s %s</text>",
- isempty(host->os_pretty_name) ? "GNU/Linux" : host->os_pretty_name,
- strempty(host->hostname),
- strempty(host->kernel_name),
- strempty(host->kernel_release),
- strempty(host->kernel_version),
- strempty(host->architecture),
- strempty(host->virtualization));
+ if (use_full_bus)
+ svg("<text x=\"20\" y=\"30\">%s %s (%s %s %s) %s %s</text>",
+ isempty(host->os_pretty_name) ? "GNU/Linux" : host->os_pretty_name,
+ strempty(host->hostname),
+ strempty(host->kernel_name),
+ strempty(host->kernel_release),
+ strempty(host->kernel_version),
+ strempty(host->architecture),
+ strempty(host->virtualization));
svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time));
svg_graph_box(m, -(double) boot->firmware_time, boot->finish_time);
@@ -753,7 +750,7 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
svg_text(true, boot->userspace_time, y, "systemd");
y++;
- for (u = times; u < times + n; u++) {
+ for (u = times; u->has_data; u++) {
char ts[FORMAT_TIMESPAN_MAX];
bool b;
@@ -802,10 +799,7 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
svg("</svg>\n");
- free_unit_times(times, (unsigned) n);
-
- n = 0;
- return n;
+ return 0;
}
static int list_dependencies_print(const char *name, unsigned int level, unsigned int branches,
@@ -1003,12 +997,12 @@ static int list_dependencies(sd_bus *bus, const char *name) {
static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- struct unit_times *times;
- unsigned int i;
+ _cleanup_(unit_times_freep) struct unit_times *times = NULL;
+ struct unit_times *u;
Hashmap *h;
int n, r;
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1020,14 +1014,14 @@ static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
if (!h)
return log_oom();
- for (i = 0; i < (unsigned) n; i++) {
- r = hashmap_put(h, times[i].name, &times[i]);
+ for (u = times; u->has_data; u++) {
+ r = hashmap_put(h, u->name, u);
if (r < 0)
return log_error_errno(r, "Failed to add entry to hashmap: %m");
}
unit_times_hashmap = h;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
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");
@@ -1040,17 +1034,16 @@ static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
list_dependencies(bus, SPECIAL_DEFAULT_TARGET);
h = hashmap_free(h);
- free_unit_times(times, (unsigned) n);
return 0;
}
static int analyze_blame(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- struct unit_times *times;
- unsigned i;
+ _cleanup_(unit_times_freep) struct unit_times *times = NULL;
+ struct unit_times *u;
int n, r;
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1060,16 +1053,15 @@ static int analyze_blame(int argc, char *argv[], void *userdata) {
qsort(times, n, sizeof(struct unit_times), compare_unit_time);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
- for (i = 0; i < (unsigned) n; i++) {
+ for (u = times; u->has_data; u++) {
char ts[FORMAT_TIMESPAN_MAX];
- if (times[i].time > 0)
- printf("%16s %s\n", format_timespan(ts, sizeof(ts), times[i].time, USEC_PER_MSEC), times[i].name);
+ if (u->time > 0)
+ printf("%16s %s\n", format_timespan(ts, sizeof(ts), u->time, USEC_PER_MSEC), u->name);
}
- free_unit_times(times, (unsigned) n);
return 0;
}
@@ -1078,7 +1070,7 @@ static int analyze_time(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *buf = NULL;
int r;
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1212,7 +1204,7 @@ static int dot(int argc, char *argv[], void *userdata) {
int r;
UnitInfo u;
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1272,18 +1264,13 @@ static int dot(int argc, char *argv[], void *userdata) {
return 0;
}
-static int dump(int argc, char *argv[], void *userdata) {
+static int dump_fallback(sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *text = NULL;
int r;
- r = acquire_bus(false, &bus);
- if (r < 0)
- return log_error_errno(r, "Failed to create bus connection: %m");
-
- pager_open(arg_no_pager, false);
+ assert(bus);
r = sd_bus_call_method(
bus,
@@ -1295,7 +1282,7 @@ static int dump(int argc, char *argv[], void *userdata) {
&reply,
NULL);
if (r < 0)
- return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Failed to issue method call Dump: %s", bus_error_message(&error, r));
r = sd_bus_message_read(reply, "s", &text);
if (r < 0)
@@ -1305,6 +1292,83 @@ static int dump(int argc, char *argv[], void *userdata) {
return 0;
}
+static int dump(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ int fd = -1;
+ int r;
+
+ r = acquire_bus(&bus, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create bus connection: %m");
+
+ (void) pager_open(arg_no_pager, false);
+
+ if (!sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD))
+ return dump_fallback(bus);
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "DumpByFileDescriptor",
+ &error,
+ &reply,
+ NULL);
+ if (r < 0) {
+ /* fall back to Dump if DumpByFileDescriptor is not supported */
+ if (!IN_SET(r, -EACCES, -EBADR))
+ return log_error_errno(r, "Failed to issue method call DumpByFileDescriptor: %s", bus_error_message(&error, r));
+
+ return dump_fallback(bus);
+ }
+
+ r = sd_bus_message_read(reply, "h", &fd);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ fflush(stdout);
+ return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0);
+}
+
+static int cat_config(int argc, char *argv[], void *userdata) {
+ char **arg;
+ int r;
+
+ (void) pager_open(arg_no_pager, false);
+
+ STRV_FOREACH(arg, argv + 1) {
+ const char *t = NULL;
+
+ if (arg != argv + 1)
+ print_separator();
+
+ if (path_is_absolute(*arg)) {
+ const char *dir;
+
+ NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) {
+ t = path_startswith(*arg, dir);
+ if (t)
+ break;
+ }
+
+ if (!t) {
+ log_error("Path %s does not start with any known prefix.", *arg);
+ return -EINVAL;
+ }
+ } else
+ t = *arg;
+
+ r = conf_files_cat(arg_root, t);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
static int set_log_level(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
@@ -1313,7 +1377,7 @@ static int set_log_level(int argc, char *argv[], void *userdata) {
assert(argc == 2);
assert(argv);
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1338,7 +1402,7 @@ static int get_log_level(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *level = NULL;
int r;
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1369,7 +1433,7 @@ static int set_log_target(int argc, char *argv[], void *userdata) {
assert(argc == 2);
assert(argv);
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1394,7 +1458,7 @@ static int get_log_target(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *target = NULL;
int r;
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1418,7 +1482,7 @@ static int get_or_set_log_target(int argc, char *argv[], void *userdata) {
}
static int dump_unit_paths(int argc, char *argv[], void *userdata) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
int r;
char **p;
@@ -1445,7 +1509,7 @@ static void dump_syscall_filter(const SyscallFilterSet *set) {
static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
bool first = true;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (strv_isempty(strv_skip(argv, 1))) {
int i;
@@ -1556,7 +1620,7 @@ static int service_watchdogs(int argc, char *argv[], void *userdata) {
assert(IN_SET(argc, 1, 2));
assert(argv);
- r = acquire_bus(false, &bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
@@ -1607,7 +1671,7 @@ static int do_verify(int argc, char *argv[], void *userdata) {
static int help(int argc, char *argv[], void *userdata) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Profile systemd, show unit dependencies, check unit files.\n\n"
@@ -1636,6 +1700,7 @@ static int help(int argc, char *argv[], void *userdata) {
" log-level [LEVEL] Get/set logging threshold for manager\n"
" log-target [TARGET] Get/set logging target for manager\n"
" dump Output state serialization of service manager\n"
+ " cat-config Show configuration file and drop-ins\n"
" unit-paths List load directories for units\n"
" syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
" verify FILE... Check unit files for correctness\n"
@@ -1655,6 +1720,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION = 0x100,
ARG_ORDER,
ARG_REQUIRE,
+ ARG_ROOT,
ARG_SYSTEM,
ARG_USER,
ARG_GLOBAL,
@@ -1671,6 +1737,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "order", no_argument, NULL, ARG_ORDER },
{ "require", no_argument, NULL, ARG_REQUIRE },
+ { "root", required_argument, NULL, ARG_ROOT },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "user", no_argument, NULL, ARG_USER },
{ "global", no_argument, NULL, ARG_GLOBAL },
@@ -1699,6 +1766,10 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_VERSION:
return version();
+ case ARG_ROOT:
+ arg_root = optarg;
+ break;
+
case ARG_SYSTEM:
arg_scope = UNIT_FILE_SYSTEM;
break;
@@ -1759,7 +1830,7 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- arg_man = !!r;
+ arg_man = r;
} else
arg_man = true;
@@ -1773,7 +1844,7 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- arg_generators = !!r;
+ arg_generators = r;
} else
arg_generators = true;
@@ -1792,6 +1863,11 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
+ if (arg_root && !streq_ptr(argv[optind], "cat-config")) {
+ log_error("Option --root is only supported for cat-config right now.");
+ return -EINVAL;
+ }
+
return 1; /* work to do */
}
@@ -1812,6 +1888,7 @@ int main(int argc, char *argv[]) {
{ "set-log-target", 2, 2, 0, set_log_target },
{ "get-log-target", VERB_ANY, 1, 0, get_log_target },
{ "dump", VERB_ANY, 1, 0, dump },
+ { "cat-config", 2, VERB_ANY, 0, cat_config },
{ "unit-paths", 1, 1, 0, dump_unit_paths },
{ "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters },
{ "verify", 2, VERB_ANY, 0, do_verify },
diff --git a/src/analyze/meson.build b/src/analyze/meson.build
index b32311413b..3a69a259b1 100644
--- a/src/analyze/meson.build
+++ b/src/analyze/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
systemd_analyze_sources = files('''
analyze.c
diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c
index 48cfaa7acc..8e1d834ab4 100644
--- a/src/ask-password/ask-password.c
+++ b/src/ask-password/ask-password.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c
index 8fedf8ebbc..2b1a1683e2 100644
--- a/src/backlight/backlight.c
+++ b/src/backlight/backlight.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "libudev.h"
@@ -103,7 +85,7 @@ static bool same_device(struct udev_device *a, struct udev_device *b) {
}
static bool validate_device(struct udev *udev, struct udev_device *device) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *enumerate = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *enumerate = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
struct udev_device *parent;
const char *v, *subsystem;
@@ -156,7 +138,7 @@ static bool validate_device(struct udev *udev, struct udev_device *device) {
first = udev_enumerate_get_list_entry(enumerate);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *other;
+ _cleanup_(udev_device_unrefp) struct udev_device *other;
struct udev_device *other_parent;
const char *other_subsystem;
@@ -234,9 +216,9 @@ static unsigned get_max_brightness(struct udev_device *device) {
* an unreadably dim screen, which would otherwise force the user to
* disable state restoration. */
static void clamp_brightness(struct udev_device *device, char **value, unsigned max_brightness) {
- int r;
unsigned brightness, new_brightness, min_brightness;
const char *subsystem;
+ int r;
r = safe_atou(*value, &brightness);
if (r < 0) {
@@ -269,11 +251,30 @@ static void clamp_brightness(struct udev_device *device, char **value, unsigned
}
}
+static bool shall_clamp(struct udev_device *d) {
+ const char *s;
+ int r;
+
+ assert(d);
+
+ s = udev_device_get_property_value(d, "ID_BACKLIGHT_CLAMP");
+ if (!s)
+ return true;
+
+ r = parse_boolean(s);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse ID_BACKLIGHT_CLAMP property, ignoring: %m");
+ return true;
+ }
+
+ return r;
+}
+
int main(int argc, char *argv[]) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
- _cleanup_free_ char *saved = NULL, *ss = NULL, *escaped_ss = NULL, *escaped_sysname = NULL, *escaped_path_id = NULL;
- const char *sysname, *path_id;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
+ _cleanup_free_ char *escaped_ss = NULL, *escaped_sysname = NULL, *escaped_path_id = NULL;
+ const char *sysname, *path_id, *ss, *saved;
unsigned max_brightness;
int r;
@@ -306,15 +307,11 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- ss = strndup(argv[2], sysname - argv[2]);
- if (!ss) {
- log_oom();
- return EXIT_FAILURE;
- }
+ ss = strndupa(argv[2], sysname - argv[2]);
sysname++;
- if (!streq(ss, "backlight") && !streq(ss, "leds")) {
+ if (!STR_IN_SET(ss, "backlight", "leds")) {
log_error("Not a backlight or LED device: '%s:%s'", ss, sysname);
return EXIT_FAILURE;
}
@@ -358,14 +355,9 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- saved = strjoin("/var/lib/systemd/backlight/", escaped_path_id, ":", escaped_ss, ":", escaped_sysname);
+ saved = strjoina("/var/lib/systemd/backlight/", escaped_path_id, ":", escaped_ss, ":", escaped_sysname);
} else
- saved = strjoin("/var/lib/systemd/backlight/", escaped_ss, ":", escaped_sysname);
-
- if (!saved) {
- log_oom();
- return EXIT_FAILURE;
- }
+ saved = strjoina("/var/lib/systemd/backlight/", escaped_ss, ":", escaped_sysname);
/* If there are multiple conflicting backlight devices, then
* their probing at boot-time might happen in any order. This
@@ -378,7 +370,7 @@ int main(int argc, char *argv[]) {
if (streq(argv[1], "load")) {
_cleanup_free_ char *value = NULL;
- const char *clamp;
+ bool clamp;
if (shall_restore_state() == 0)
return EXIT_SUCCESS;
@@ -386,18 +378,34 @@ int main(int argc, char *argv[]) {
if (!validate_device(udev, device))
return EXIT_SUCCESS;
+ clamp = shall_clamp(device);
+
r = read_one_line_file(saved, &value);
- if (r < 0) {
+ if (r == -ENOENT) {
+ const char *curval;
- if (r == -ENOENT)
+ /* Fallback to clamping current brightness or exit early if
+ * clamping is not supported/enabled. */
+ if (!clamp)
return EXIT_SUCCESS;
+ curval = udev_device_get_sysattr_value(device, "brightness");
+ if (!curval) {
+ log_warning("Failed to read 'brightness' attribute.");
+ return EXIT_FAILURE;
+ }
+
+ value = strdup(curval);
+ if (!value) {
+ log_oom();
+ return EXIT_FAILURE;
+ }
+ } else if (r < 0) {
log_error_errno(r, "Failed to read %s: %m", saved);
return EXIT_FAILURE;
}
- clamp = udev_device_get_property_value(device, "ID_BACKLIGHT_CLAMP");
- if (!clamp || parse_boolean(clamp) != 0) /* default to clamping */
+ if (clamp)
clamp_brightness(device, &value, max_brightness);
r = udev_device_set_sysattr_value(device, "brightness", value);
diff --git a/src/basic/MurmurHash2.c b/src/basic/MurmurHash2.c
index 47adfb4d0a..5859af0a81 100644
--- a/src/basic/MurmurHash2.c
+++ b/src/basic/MurmurHash2.c
@@ -30,7 +30,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
// Other compilers
-#else // defined(_MSC_VER)
+#else // defined(_MSC_VER)
#define BIG_CONSTANT(x) (x##LLU)
diff --git a/src/basic/MurmurHash2.h b/src/basic/MurmurHash2.h
index 93362dd485..6104b4fbe6 100644
--- a/src/basic/MurmurHash2.h
+++ b/src/basic/MurmurHash2.h
@@ -18,7 +18,7 @@ typedef unsigned __int64 uint64_t;
// Other compilers
-#else // defined(_MSC_VER)
+#else // defined(_MSC_VER)
#include <stdint.h>
diff --git a/src/basic/af-list.c b/src/basic/af-list.c
index fa81a69e0e..866a1d4317 100644
--- a/src/basic/af-list.c
+++ b/src/basic/af-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
#include <sys/socket.h>
diff --git a/src/basic/af-list.h b/src/basic/af-list.h
index 1684bc6a0f..8342323b8a 100644
--- a/src/basic/af-list.h
+++ b/src/basic/af-list.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/socket.h>
#include "string-util.h"
diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c
index cdde4f2859..405445eac1 100644
--- a/src/basic/alloc-util.c
+++ b/src/basic/alloc-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdint.h>
#include <string.h>
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h
index ec7808c1f7..ebe42889ea 100644
--- a/src/basic/alloc-util.h
+++ b/src/basic/alloc-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <stddef.h>
#include <stdlib.h>
@@ -31,9 +12,17 @@
#define new0(t, n) ((t*) calloc((n), sizeof(t)))
-#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
+#define newa(t, n) \
+ ({ \
+ assert(!size_multiply_overflow(sizeof(t), n)); \
+ (t*) alloca(sizeof(t)*(n)); \
+ })
-#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
+#define newa0(t, n) \
+ ({ \
+ assert(!size_multiply_overflow(sizeof(t), n)); \
+ (t*) alloca0(sizeof(t)*(n)); \
+ })
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
@@ -130,3 +119,12 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
_new_ = alloca_align(_size_, (align)); \
(void*)memset(_new_, 0, _size_); \
})
+
+/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to
+ * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
+#define TAKE_PTR(ptr) \
+ ({ \
+ typeof(ptr) _ptr_ = (ptr); \
+ (ptr) = NULL; \
+ _ptr_; \
+ })
diff --git a/src/basic/architecture.c b/src/basic/architecture.c
index 46157061ed..85837b5ebf 100644
--- a/src/basic/architecture.c
+++ b/src/basic/architecture.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/utsname.h>
diff --git a/src/basic/architecture.h b/src/basic/architecture.h
index c81a1c2f44..443e890eab 100644
--- a/src/basic/architecture.h
+++ b/src/basic/architecture.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <endian.h>
#include "macro.h"
diff --git a/src/basic/arphrd-list.c b/src/basic/arphrd-list.c
index 5df93a59c1..a7ae4b8162 100644
--- a/src/basic/arphrd-list.c
+++ b/src/basic/arphrd-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if_arp.h>
#include <string.h>
diff --git a/src/basic/arphrd-list.h b/src/basic/arphrd-list.h
index 2222e92c8a..5dcfe5e12d 100644
--- a/src/basic/arphrd-list.h
+++ b/src/basic/arphrd-list.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
const char *arphrd_to_name(int id);
int arphrd_from_name(const char *name);
diff --git a/src/basic/async.c b/src/basic/async.c
index b6c6d6a80b..1c4b575b05 100644
--- a/src/basic/async.c
+++ b/src/basic/async.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <pthread.h>
diff --git a/src/basic/async.h b/src/basic/async.h
index 01c975bb30..3160613184 100644
--- a/src/basic/async.h
+++ b/src/basic/async.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int asynchronous_job(void* (*func)(void *p), void *arg);
int asynchronous_sync(pid_t *ret_pid);
diff --git a/src/basic/audit-util.c b/src/basic/audit-util.c
index 1e897cb982..5cbaef3eba 100644
--- a/src/basic/audit-util.c
+++ b/src/basic/audit-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <linux/netlink.h>
diff --git a/src/basic/audit-util.h b/src/basic/audit-util.h
index dba15de8ee..c9fc49871d 100644
--- a/src/basic/audit-util.h
+++ b/src/basic/audit-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
diff --git a/src/basic/barrier.c b/src/basic/barrier.c
index cd3638b676..587852aac8 100644
--- a/src/basic/barrier.c
+++ b/src/basic/barrier.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/basic/barrier.h b/src/basic/barrier.h
index 7260d751c4..96a9955c6f 100644
--- a/src/basic/barrier.h
+++ b/src/basic/barrier.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
#include <stdint.h>
diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c
index f1aa7c5e51..c17c6a7a02 100644
--- a/src/basic/bitmap.c
+++ b/src/basic/bitmap.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stddef.h>
diff --git a/src/basic/bitmap.h b/src/basic/bitmap.h
index f1d822c643..7ff5cffd26 100644
--- a/src/basic/bitmap.h
+++ b/src/basic/bitmap.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
diff --git a/src/basic/blkid-util.h b/src/basic/blkid-util.h
index 3aba76b79e..e4eb600ed6 100644
--- a/src/basic/blkid-util.h
+++ b/src/basic/blkid-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#if HAVE_BLKID
#include <blkid.h>
#endif
@@ -28,5 +9,4 @@
#if HAVE_BLKID
DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
-#define _cleanup_blkid_free_probe_ _cleanup_(blkid_free_probep)
#endif
diff --git a/src/basic/blockdev-util.c b/src/basic/blockdev-util.c
index 3a8f8d1c27..42b311eccd 100644
--- a/src/basic/blockdev-util.c
+++ b/src/basic/blockdev-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/stat.h>
#include <sys/statfs.h>
@@ -94,38 +76,26 @@ int get_block_device(const char *path, dev_t *dev) {
if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
return btrfs_get_block_device(path, dev);
+ *dev = 0;
return 0;
}
-int get_block_device_harder(const char *path, dev_t *dev) {
+int block_get_originating(dev_t dt, dev_t *ret) {
_cleanup_closedir_ DIR *d = NULL;
_cleanup_free_ char *t = NULL;
char p[SYS_BLOCK_PATH_MAX("/slaves")];
struct dirent *de, *found = NULL;
- const char *q;
unsigned maj, min;
- dev_t dt;
+ const char *q;
int r;
- assert(path);
- assert(dev);
-
- /* Gets the backing block device for a file system, and
- * handles LUKS encrypted file systems, looking for its
- * immediate parent, if there is one. */
-
- r = get_block_device(path, &dt);
- if (r <= 0)
- return r;
+ /* For the specified block device tries to chase it through the layers, in case LUKS-style DM stacking is used,
+ * trying to find the next underlying layer. */
xsprintf_sys_block_path(p, "/slaves", dt);
d = opendir(p);
- if (!d) {
- if (errno == ENOENT)
- goto fallback;
-
+ if (!d)
return -errno;
- }
FOREACH_DIRENT_ALL(de, d, return -errno) {
@@ -153,34 +123,28 @@ int get_block_device_harder(const char *path, dev_t *dev) {
return -ENOMEM;
r = read_one_line_file(u, &a);
- if (r < 0) {
- log_debug_errno(r, "Failed to read %s: %m", u);
- goto fallback;
- }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to read %s: %m", u);
r = read_one_line_file(v, &b);
- if (r < 0) {
- log_debug_errno(r, "Failed to read %s: %m", v);
- goto fallback;
- }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to read %s: %m", v);
/* Check if the parent device is the same. If not, then the two backing devices are on
* different physical devices, and we don't support that. */
if (!streq(a, b))
- goto fallback;
+ return -ENOTUNIQ;
}
found = de;
}
if (!found)
- goto fallback;
+ return -ENOENT;
q = strjoina(p, "/", found->d_name, "/dev");
r = read_one_line_file(q, &t);
- if (r == -ENOENT)
- goto fallback;
if (r < 0)
return r;
@@ -188,12 +152,28 @@ int get_block_device_harder(const char *path, dev_t *dev) {
return -EINVAL;
if (maj == 0)
- goto fallback;
+ return -ENOENT;
- *dev = makedev(maj, min);
+ *ret = makedev(maj, min);
return 1;
+}
+
+int get_block_device_harder(const char *path, dev_t *ret) {
+ int r;
+
+ assert(path);
+ assert(ret);
+
+ /* Gets the backing block device for a file system, and handles LUKS encrypted file systems, looking for its
+ * immediate parent, if there is one. */
+
+ r = get_block_device(path, ret);
+ if (r <= 0)
+ return r;
+
+ r = block_get_originating(*ret, ret);
+ if (r < 0)
+ log_debug_errno(r, "Failed to chase block device '%s', ignoring: %m", path);
-fallback:
- *dev = dt;
return 1;
}
diff --git a/src/basic/blockdev-util.h b/src/basic/blockdev-util.h
index 642b7ce522..6d8a796568 100644
--- a/src/basic/blockdev-util.h
+++ b/src/basic/blockdev-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/types.h>
#include "macro.h"
@@ -32,6 +13,7 @@
xsprintf(buf, "/sys/dev/block/%u:%u%s", major(devno), minor(devno), strempty(suffix))
int block_get_whole_disk(dev_t d, dev_t *ret);
+int block_get_originating(dev_t d, dev_t *ret);
int get_block_device(const char *path, dev_t *dev);
diff --git a/src/basic/bpf-program.c b/src/basic/bpf-program.c
index a244742f91..ed57f9ffdc 100644
--- a/src/basic/bpf-program.c
+++ b/src/basic/bpf-program.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <sys/stat.h>
@@ -42,8 +24,8 @@ int bpf_program_new(uint32_t prog_type, BPFProgram **ret) {
p->prog_type = prog_type;
p->kernel_fd = -1;
- *ret = p;
- p = NULL;
+ *ret = TAKE_PTR(p);
+
return 0;
}
diff --git a/src/basic/bpf-program.h b/src/basic/bpf-program.h
index 3d6c5e50ef..c21eb2f72a 100644
--- a/src/basic/bpf-program.h
+++ b/src/basic/bpf-program.h
@@ -1,27 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
- [Except for the stuff copy/pasted from the kernel sources, see below]
-***/
-
#include <linux/bpf.h>
#include <stdint.h>
#include <sys/syscall.h>
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index 0db8292e70..6d2490f3d7 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -290,8 +272,10 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) {
return -errno;
/* We won't do this for btrfs RAID */
- if (fsi.num_devices != 1)
+ if (fsi.num_devices != 1) {
+ *dev = 0;
return 0;
+ }
for (id = 1; id <= fsi.max_id; id++) {
struct btrfs_ioctl_dev_info_args di = {
@@ -511,7 +495,7 @@ int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) {
(usec_t) le32toh(ri->otime.nsec) / NSEC_PER_USEC;
ret->subvol_id = subvol_id;
- ret->read_only = !!(le64toh(ri->flags) & BTRFS_ROOT_SUBVOL_RDONLY);
+ ret->read_only = le64toh(ri->flags) & BTRFS_ROOT_SUBVOL_RDONLY;
assert_cc(sizeof(ri->uuid) == sizeof(ret->uuid));
memcpy(&ret->uuid, ri->uuid, sizeof(ret->uuid));
@@ -1841,8 +1825,7 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {
return 0;
}
- *ret = items;
- items = NULL;
+ *ret = TAKE_PTR(items);
return (int) n_items;
}
diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h
index 952b3c26da..a594387b5a 100644
--- a/src/basic/btrfs-util.h
+++ b/src/basic/btrfs-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
diff --git a/src/basic/build.h b/src/basic/build.h
index 0d078efe6f..2c46550300 100644
--- a/src/basic/build.h
+++ b/src/basic/build.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#if HAVE_PAM
#define _PAM_FEATURE_ "+PAM"
#else
diff --git a/src/basic/bus-label.c b/src/basic/bus-label.c
index a072d0ad5d..1613cf7fd7 100644
--- a/src/basic/bus-label.c
+++ b/src/basic/bus-label.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdlib.h>
diff --git a/src/basic/bus-label.h b/src/basic/bus-label.h
index 5c6bc1f267..664cfaf67f 100644
--- a/src/basic/bus-label.h
+++ b/src/basic/bus-label.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 8f3bb9102f..8cb645aeac 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <alloca.h>
#include <ctype.h>
@@ -43,6 +25,12 @@
#define MIN_YEAR 1970
#define MAX_YEAR 2199
+/* An arbitrary limit on the length of the chains of components. We don't want to
+ * build a very long linked list, which would be slow to iterate over and might cause
+ * our stack to overflow. It's unlikely that legitimate uses require more than a few
+ * linked compenents anyway. */
+#define CALENDARSPEC_COMPONENTS_MAX 240
+
static void free_chain(CalendarComponent *c) {
CalendarComponent *n;
@@ -91,8 +79,8 @@ static int component_compare(const void *_a, const void *_b) {
}
static void normalize_chain(CalendarComponent **c) {
- unsigned n = 0, k;
CalendarComponent **b, *i, **j, *next;
+ size_t n = 0, k;
assert(c);
@@ -111,7 +99,7 @@ static void normalize_chain(CalendarComponent **c) {
if (n <= 1)
return;
- j = b = alloca(sizeof(CalendarComponent*) * n);
+ j = b = newa(CalendarComponent*, n);
for (i = *c; i; i = i->next)
*(j++) = i;
@@ -427,7 +415,7 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
assert(c);
for (;;) {
- unsigned i;
+ size_t i;
for (i = 0; i < ELEMENTSOF(day_nr); i++) {
size_t skip;
@@ -587,7 +575,8 @@ static int calendarspec_from_time_t(CalendarSpec *c, time_t time) {
CalendarComponent *year = NULL, *month = NULL, *day = NULL, *hour = NULL, *minute = NULL, *us = NULL;
int r;
- assert_se(gmtime_r(&time, &tm));
+ if (!gmtime_r(&time, &tm))
+ return -ERANGE;
r = const_chain(tm.tm_year + 1900, &year);
if (r < 0)
@@ -623,15 +612,16 @@ static int calendarspec_from_time_t(CalendarSpec *c, time_t time) {
return 0;
}
-static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
+static int prepend_component(const char **p, bool usec, unsigned nesting, CalendarComponent **c) {
int r, start, stop = -1, repeat = 0;
CalendarComponent *cc;
- const char *e;
+ const char *e = *p;
assert(p);
assert(c);
- e = *p;
+ if (nesting > CALENDARSPEC_COMPONENTS_MAX)
+ return -ENOBUFS;
r = parse_component_decimal(&e, usec, &start);
if (r < 0)
@@ -673,7 +663,7 @@ static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
if (*e ==',') {
*p += 1;
- return prepend_component(p, usec, c);
+ return prepend_component(p, usec, nesting + 1, c);
}
return 0;
@@ -702,7 +692,7 @@ static int parse_chain(const char **p, bool usec, CalendarComponent **c) {
return 0;
}
- r = prepend_component(&t, usec, &cc);
+ r = prepend_component(&t, usec, 0, &cc);
if (r < 0) {
free_chain(cc);
return r;
@@ -896,7 +886,7 @@ fail:
int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
const char *utc;
- CalendarSpec *c;
+ _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
int r;
assert(p);
@@ -942,60 +932,56 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
const char *last_space;
last_space = strrchr(p, ' ');
- if (last_space != NULL && timezone_is_valid(last_space + 1)) {
+ if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG)) {
c->timezone = strdup(last_space + 1);
- if (!c->timezone) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!c->timezone)
+ return -ENOMEM;
p = strndupa(p, last_space - p);
}
}
}
- if (isempty(p)) {
- r = -EINVAL;
- goto fail;
- }
+ if (isempty(p))
+ return -EINVAL;
if (strcaseeq(p, "minutely")) {
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "hourly")) {
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "daily")) {
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "monthly")) {
r = const_chain(1, &c->day);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "annually") ||
strcaseeq(p, "yearly") ||
@@ -1003,19 +989,19 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(1, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(1, &c->day);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "weekly")) {
@@ -1023,40 +1009,40 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "quarterly")) {
r = const_chain(1, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(4, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(7, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(10, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(1, &c->day);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "biannually") ||
strcaseeq(p, "bi-annually") ||
@@ -1065,59 +1051,51 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(1, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(7, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(1, &c->day);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else {
r = parse_weekdays(&p, c);
if (r < 0)
- goto fail;
+ return r;
r = parse_date(&p, c);
if (r < 0)
- goto fail;
+ return r;
if (r == 0) {
r = parse_calendar_time(&p, c);
if (r < 0)
- goto fail;
+ return r;
}
- if (*p != 0) {
- r = -EINVAL;
- goto fail;
- }
+ if (*p != 0)
+ return -EINVAL;
}
r = calendar_spec_normalize(c);
if (r < 0)
- goto fail;
+ return r;
- if (!calendar_spec_valid(c)) {
- r = -EINVAL;
- goto fail;
- }
+ if (!calendar_spec_valid(c))
+ return -EINVAL;
- *spec = c;
+ *spec = TAKE_PTR(c);
return 0;
-
-fail:
- calendar_spec_free(c);
- return r;
}
static int find_end_of_month(struct tm *tm, bool utc, int day) {
@@ -1167,7 +1145,7 @@ static int find_matching_component(const CalendarSpec *spec, const CalendarCompo
} else if (c->repeat > 0) {
int k;
- k = start + c->repeat * ((*val - start + c->repeat - 1) / c->repeat);
+ k = start + c->repeat * DIV_ROUND_UP(*val - start, c->repeat);
if ((!d_set || k < d) && (stop < 0 || k <= stop)) {
d = k;
diff --git a/src/basic/calendarspec.h b/src/basic/calendarspec.h
index 124f7f5880..3bf8a39e1a 100644
--- a/src/basic/calendarspec.h
+++ b/src/basic/calendarspec.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
/* A structure for specifying (possibly repetitive) points in calendar
* time, a la cron */
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
index c4557666ef..bfcda33520 100644
--- a/src/basic/cap-list.c
+++ b/src/basic/cap-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -103,8 +85,7 @@ int capability_set_to_string_alloc(uint64_t set, char **s) {
str[n > 0 ? n - 1 : 0] = '\0'; /* truncate the last space, if it's there */
- *s = str;
- str = NULL;
+ *s = TAKE_PTR(str);
return 0;
}
diff --git a/src/basic/cap-list.h b/src/basic/cap-list.h
index ca9f4aa970..ab41924d9c 100644
--- a/src/basic/cap-list.h
+++ b/src/basic/cap-list.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
const char *capability_to_name(int id);
int capability_from_name(const char *name);
int capability_list_length(void);
diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c
index 97778c55ab..6ae35e078b 100644
--- a/src/basic/capability-util.c
+++ b/src/basic/capability-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <grp.h>
@@ -241,10 +223,10 @@ finish:
}
static int drop_from_file(const char *fn, uint64_t keep) {
- int r, k;
- uint32_t hi, lo;
+ _cleanup_free_ char *p = NULL;
uint64_t current, after;
- char *p;
+ uint32_t hi, lo;
+ int r, k;
r = read_one_line_file(fn, &p);
if (r < 0)
@@ -254,8 +236,6 @@ static int drop_from_file(const char *fn, uint64_t keep) {
assert_cc(sizeof(lo) == sizeof(unsigned));
k = sscanf(p, "%u %u", &lo, &hi);
- free(p);
-
if (k != 2)
return -EIO;
@@ -268,13 +248,7 @@ static int drop_from_file(const char *fn, uint64_t keep) {
lo = (unsigned) (after & 0xFFFFFFFFULL);
hi = (unsigned) ((after >> 32ULL) & 0xFFFFFFFFULL);
- if (asprintf(&p, "%u %u", lo, hi) < 0)
- return -ENOMEM;
-
- r = write_string_file(fn, p, WRITE_STRING_FILE_CREATE);
- free(p);
-
- return r;
+ return write_string_filef(fn, WRITE_STRING_FILE_CREATE, "%u %u", lo, hi);
}
int capability_bounding_set_drop_usermode(uint64_t keep) {
@@ -314,8 +288,7 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
if (prctl(PR_SET_KEEPCAPS, 1) < 0)
return log_error_errno(errno, "Failed to enable keep capabilities flag: %m");
- r = setresuid(uid, uid, uid);
- if (r < 0)
+ if (setresuid(uid, uid, uid) < 0)
return log_error_errno(errno, "Failed to change user ID: %m");
if (prctl(PR_SET_KEEPCAPS, 0) < 0)
diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h
index fd9370ecb7..4a4a86093a 100644
--- a/src/basic/capability-util.h
+++ b/src/basic/capability-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdint.h>
#include <sys/capability.h>
@@ -54,7 +35,7 @@ static inline void cap_free_charpp(char **p) {
static inline bool cap_test_all(uint64_t caps) {
uint64_t m;
m = (UINT64_C(1) << (cap_last_cap() + 1)) - 1;
- return (caps & m) == m;
+ return FLAGS_SET(caps, m);
}
bool ambient_capabilities_supported(void);
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 296da2898b..038ece4b06 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -434,7 +416,7 @@ int cg_migrate(
* exist in the root cgroup, we only check for
* them there. */
if (cfrom &&
- (isempty(pfrom) || path_equal(pfrom, "/")) &&
+ empty_or_root(pfrom) &&
is_kernel_thread(pid) > 0)
continue;
@@ -641,7 +623,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
if (!t)
return -ENOMEM;
- *fs = path_kill_slashes(t);
+ *fs = path_simplify(t, false);
return 0;
}
@@ -658,7 +640,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
if (r < 0)
return r;
- path_kill_slashes(*fs);
+ path_simplify(*fs, false);
return 0;
}
@@ -767,6 +749,9 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
return r;
}
+/* Create a cgroup in the hierarchy of controller.
+ * Returns 0 if the group already existed, 1 on success, negative otherwise.
+ */
int cg_create(const char *controller, const char *path) {
_cleanup_free_ char *fs = NULL;
int r;
@@ -1198,7 +1183,7 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
assert(path);
/* The root cgroup is always populated */
- if (controller && (isempty(path) || path_equal(path, "/")))
+ if (controller && empty_or_root(path))
return false;
r = cg_unified_controller(controller);
@@ -1263,7 +1248,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
if (!t)
return -ENOMEM;
- *path = path_kill_slashes(t);
+ *path = path_simplify(t, false);
}
if (controller)
@@ -1315,7 +1300,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
return -EINVAL;
}
- path_kill_slashes(u);
+ path_simplify(u, false);
}
if (controller)
@@ -1346,7 +1331,7 @@ int cg_mangle_path(const char *path, char **result) {
if (!t)
return -ENOMEM;
- *result = path_kill_slashes(t);
+ *result = path_simplify(t, false);
return 0;
}
@@ -1424,10 +1409,9 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
if (r < 0)
return r;
- if (c == raw) {
- *cgroup = raw;
- raw = NULL;
- } else {
+ if (c == raw)
+ *cgroup = TAKE_PTR(raw);
+ else {
char *n;
n = strdup(c);
@@ -1977,6 +1961,14 @@ int cg_slice_to_path(const char *unit, char **ret) {
_cleanup_free_ char *escaped = NULL;
char n[dash - p + sizeof(".slice")];
+#if HAS_FEATURE_MEMORY_SANITIZER
+ /* msan doesn't instrument stpncpy, so it thinks
+ * n is later used unitialized:
+ * https://github.com/google/sanitizers/issues/926
+ */
+ zero(n);
+#endif
+
/* Don't allow trailing or double dashes */
if (IN_SET(dash[1], 0, '-'))
return -EINVAL;
@@ -2002,8 +1994,7 @@ int cg_slice_to_path(const char *unit, char **ret) {
if (!strextend(&s, e, NULL))
return -ENOMEM;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
@@ -2111,23 +2102,29 @@ done:
int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) {
CGroupController c;
+ bool created;
int r;
/* This one will create a cgroup in our private tree, but also
* duplicate it in the trees specified in mask, and remove it
- * in all others */
+ * in all others.
+ *
+ * Returns 0 if the group already existed in the systemd hierarchy,
+ * 1 on success, negative otherwise.
+ */
/* First create the cgroup in our own hierarchy. */
r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
if (r < 0)
return r;
+ created = !!r;
/* If we are in the unified hierarchy, we are done now */
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
- return 0;
+ return created;
/* Otherwise, do the same in the other hierarchies */
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
@@ -2142,7 +2139,7 @@ int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path
(void) cg_trim(n, path, true);
}
- return 0;
+ return created;
}
int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) {
@@ -2293,8 +2290,7 @@ int cg_mask_to_string(CGroupMask mask, char **ret) {
assert(s);
s[n] = 0;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
@@ -2443,8 +2439,7 @@ int cg_kernel_controllers(Set **ret) {
return r;
}
- *ret = controllers;
- controllers = NULL;
+ *ret = TAKE_PTR(controllers);
return 0;
}
@@ -2475,7 +2470,7 @@ static int cg_unified_update(void) {
return 0;
if (statfs("/sys/fs/cgroup/", &fs) < 0)
- return log_debug_errno(errno, "statfs(\"/sys/fs/cgroup/\" failed: %m");
+ return log_debug_errno(errno, "statfs(\"/sys/fs/cgroup/\") failed: %m");
if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) {
log_debug("Found cgroup2 on /sys/fs/cgroup/, full unified hierarchy");
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index 068df102f7..1a28a8163a 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <dirent.h>
#include <stdbool.h>
#include <stdint.h>
diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c
index 3635deee4e..4ec14515eb 100644
--- a/src/basic/chattr-util.c
+++ b/src/basic/chattr-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/basic/chattr-util.h b/src/basic/chattr-util.h
index a4ddaeeb8c..0c0816344a 100644
--- a/src/basic/chattr-util.h
+++ b/src/basic/chattr-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int chattr_fd(int fd, unsigned value, unsigned mask);
int chattr_path(const char *p, unsigned value, unsigned mask);
diff --git a/src/basic/clock-util.c b/src/basic/clock-util.c
index e2499099b6..3ea016af0e 100644
--- a/src/basic/clock-util.c
+++ b/src/basic/clock-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/basic/clock-util.h b/src/basic/clock-util.h
index b90c31fb78..b9db54eac9 100644
--- a/src/basic/clock-util.h
+++ b/src/basic/clock-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <time.h>
int clock_is_localtime(const char* adjtime_path);
diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c
index 8b4129e1cd..d6ef0e941e 100644
--- a/src/basic/conf-files.c
+++ b/src/basic/conf-files.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -26,6 +8,7 @@
#include <string.h>
#include "conf-files.h"
+#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "hashmap.h"
@@ -33,17 +16,28 @@
#include "macro.h"
#include "missing.h"
#include "path-util.h"
+#include "set.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
#include "util.h"
-static int files_add(Hashmap *h, const char *suffix, const char *root, unsigned flags, const char *path) {
+static int files_add(
+ Hashmap *h,
+ Set *masked,
+ const char *suffix,
+ const char *root,
+ unsigned flags,
+ const char *path) {
+
_cleanup_closedir_ DIR *dir = NULL;
const char *dirpath;
struct dirent *de;
int r;
+ assert(h);
+ assert((flags & CONF_FILES_FILTER_MASKED) == 0 || masked);
assert(path);
dirpath = prefix_roota(root, path);
@@ -52,62 +46,89 @@ static int files_add(Hashmap *h, const char *suffix, const char *root, unsigned
if (!dir) {
if (errno == ENOENT)
return 0;
- return -errno;
+
+ return log_debug_errno(errno, "Failed to open directory '%s': %m", dirpath);
}
FOREACH_DIRENT(de, dir, return -errno) {
- char *p;
+ struct stat st;
+ char *p, *key;
+
+ /* Does this match the suffix? */
+ if (suffix && !endswith(de->d_name, suffix))
+ continue;
- if (!dirent_is_file_with_suffix(de, suffix)) {
- log_debug("Ignoring %s/%s, because it's not a regular file with suffix %s.", dirpath, de->d_name, strna(suffix));
+ /* Has this file already been found in an earlier directory? */
+ if (hashmap_contains(h, de->d_name)) {
+ log_debug("Skipping overridden file '%s/%s'.", dirpath, de->d_name);
continue;
}
- if (flags & CONF_FILES_EXECUTABLE) {
- struct stat st;
+ /* Has this been masked in an earlier directory? */
+ if ((flags & CONF_FILES_FILTER_MASKED) && set_contains(masked, de->d_name)) {
+ log_debug("File '%s/%s' is masked by previous entry.", dirpath, de->d_name);
+ continue;
+ }
+
+ /* Read file metadata if we shall validate the check for file masks, for node types or whether the node is marked executable. */
+ if (flags & (CONF_FILES_FILTER_MASKED|CONF_FILES_REGULAR|CONF_FILES_DIRECTORY|CONF_FILES_EXECUTABLE))
+ if (fstatat(dirfd(dir), de->d_name, &st, 0) < 0) {
+ log_debug_errno(errno, "Failed to stat '%s/%s', ignoring: %m", dirpath, de->d_name);
+ continue;
+ }
+
+ /* Is this a masking entry? */
+ if ((flags & CONF_FILES_FILTER_MASKED))
+ if (null_or_empty(&st)) {
+ /* Mark this one as masked */
+ r = set_put_strdup(masked, de->d_name);
+ if (r < 0)
+ return r;
+
+ log_debug("File '%s/%s' is a mask.", dirpath, de->d_name);
+ continue;
+ }
+
+ /* Does this node have the right type? */
+ if (flags & (CONF_FILES_REGULAR|CONF_FILES_DIRECTORY))
+ if (!((flags & CONF_FILES_DIRECTORY) && S_ISDIR(st.st_mode)) &&
+ !((flags & CONF_FILES_REGULAR) && S_ISREG(st.st_mode))) {
+ log_debug("Ignoring '%s/%s', as it is not a of the right type.", dirpath, de->d_name);
+ continue;
+ }
+ /* Does this node have the executable bit set? */
+ if (flags & CONF_FILES_EXECUTABLE)
/* As requested: check if the file is marked exectuable. Note that we don't check access(X_OK)
* here, as we care about whether the file is marked executable at all, and not whether it is
- * executable for us, because if such errors are stuff we should log about. */
+ * executable for us, because if so, such errors are stuff we should log about. */
- if (fstatat(dirfd(dir), de->d_name, &st, 0) < 0) {
- log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", dirpath, de->d_name);
+ if ((st.st_mode & 0111) == 0) { /* not executable */
+ log_debug("Ignoring '%s/%s', as it is not marked executable.", dirpath, de->d_name);
continue;
}
- if (!null_or_empty(&st)) {
- /* A mask is a symlink to /dev/null or an empty file. It does not even
- * have to be executable. Other entries must be regular executable files
- * or symlinks to them. */
- if (S_ISREG(st.st_mode)) {
- if ((st.st_mode & 0111) == 0) { /* not executable */
- log_debug("Ignoring %s/%s, as it is not marked executable.",
- dirpath, de->d_name);
- continue;
- }
- } else {
- log_debug("Ignoring %s/%s, as it is neither a regular file nor a mask.",
- dirpath, de->d_name);
- continue;
- }
- }
- }
+ if (flags & CONF_FILES_BASENAME) {
+ p = strdup(de->d_name);
+ if (!p)
+ return -ENOMEM;
- p = strjoin(dirpath, "/", de->d_name);
- if (!p)
- return -ENOMEM;
+ key = p;
+ } else {
+ p = strjoin(dirpath, "/", de->d_name);
+ if (!p)
+ return -ENOMEM;
- r = hashmap_put(h, basename(p), p);
- if (r == -EEXIST) {
- log_debug("Skipping overridden file: %s.", p);
- free(p);
- } else if (r < 0) {
- free(p);
- return r;
- } else if (r == 0) {
- log_debug("Duplicate file %s", p);
+ key = basename(p);
+ }
+
+ r = hashmap_put(h, key, p);
+ if (r < 0) {
free(p);
+ return log_debug_errno(r, "Failed to add item to hashmap: %m");
}
+
+ assert(r > 0);
}
return 0;
@@ -123,6 +144,7 @@ static int base_cmp(const void *a, const void *b) {
static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, unsigned flags, char **dirs) {
_cleanup_hashmap_free_ Hashmap *fh = NULL;
+ _cleanup_set_free_free_ Set *masked = NULL;
char **files, **p;
int r;
@@ -132,12 +154,18 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const
if (!path_strv_resolve_uniq(dirs, root))
return -ENOMEM;
- fh = hashmap_new(&string_hash_ops);
+ fh = hashmap_new(&path_hash_ops);
if (!fh)
return -ENOMEM;
+ if (flags & CONF_FILES_FILTER_MASKED) {
+ masked = set_new(&path_hash_ops);
+ if (!masked)
+ return -ENOMEM;
+ }
+
STRV_FOREACH(p, dirs) {
- r = files_add(fh, suffix, root, flags, *p);
+ r = files_add(fh, masked, suffix, root, flags, *p);
if (r == -ENOMEM)
return r;
if (r < 0)
@@ -165,8 +193,8 @@ int conf_files_insert(char ***strv, const char *root, char **dirs, const char *p
* - do nothing if our new entry matches the existing entry,
* - replace the existing entry if our new entry has higher priority.
*/
+ size_t i;
char *t;
- unsigned i;
int r;
for (i = 0; i < strv_length(*strv); i++) {
@@ -269,3 +297,71 @@ int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, u
return conf_files_list_strv_internal(strv, suffix, root, flags, d);
}
+
+int conf_files_list_with_replacement(
+ const char *root,
+ char **config_dirs,
+ const char *replacement,
+ char ***files,
+ char **replace_file) {
+
+ _cleanup_strv_free_ char **f = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ assert(config_dirs);
+ assert(files);
+ assert(replace_file || !replacement);
+
+ r = conf_files_list_strv(&f, ".conf", root, 0, (const char* const*) config_dirs);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enumerate config files: %m");
+
+ if (replacement) {
+ r = conf_files_insert(&f, root, config_dirs, replacement);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extend config file list: %m");
+
+ p = path_join(root, replacement, NULL);
+ if (!p)
+ return log_oom();
+ }
+
+ *files = TAKE_PTR(f);
+ if (replace_file)
+ *replace_file = TAKE_PTR(p);
+ return 0;
+}
+
+int conf_files_cat(const char *root, const char *name) {
+ _cleanup_strv_free_ char **dirs = NULL, **files = NULL;
+ _cleanup_free_ char *path = NULL;
+ const char *dir;
+ char **t;
+ int r;
+
+ NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) {
+ assert(endswith(dir, "/"));
+ r = strv_extendf(&dirs, "%s%s.d", dir, name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to build directory list: %m");
+ }
+
+ r = conf_files_list_strv(&files, ".conf", root, 0, (const char* const*) dirs);
+ if (r < 0)
+ return log_error_errno(r, "Failed to query file list: %m");
+
+ path = path_join(root, "/etc", name);
+ if (!path)
+ return log_oom();
+
+ if (DEBUG_LOGGING) {
+ log_debug("Looking for configuration in:");
+ log_debug(" %s", path);
+ STRV_FOREACH(t, dirs)
+ log_debug(" %s/*.conf", *t);
+ }
+
+ /* show */
+ return cat_files(path, files, CAT_FLAGS_MAIN_FILE_OPTIONAL);
+}
diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h
index 5dc83578e4..9da03ed228 100644
--- a/src/basic/conf-files.h
+++ b/src/basic/conf-files.h
@@ -1,28 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
- Copyright 2010-2012 Kay Sievers
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
enum {
- CONF_FILES_EXECUTABLE = 1,
+ CONF_FILES_EXECUTABLE = 1 << 0,
+ CONF_FILES_REGULAR = 1 << 1,
+ CONF_FILES_DIRECTORY = 1 << 2,
+ CONF_FILES_BASENAME = 1 << 3,
+ CONF_FILES_FILTER_MASKED = 1 << 4,
};
int conf_files_list(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dir, ...);
@@ -30,3 +15,10 @@ int conf_files_list_strv(char ***ret, const char *suffix, const char *root, unsi
int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs);
int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path);
int conf_files_insert_nulstr(char ***strv, const char *root, const char *dirs, const char *path);
+int conf_files_list_with_replacement(
+ const char *root,
+ char **config_dirs,
+ const char *replacement,
+ char ***files,
+ char **replace_file);
+int conf_files_cat(const char *root, const char *name);
diff --git a/src/basic/copy.c b/src/basic/copy.c
index a9e1a87622..e06a503a29 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -42,6 +24,7 @@
#include "io-util.h"
#include "macro.h"
#include "missing.h"
+#include "mount-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -49,56 +32,149 @@
#include "user-util.h"
#include "xattr-util.h"
-#define COPY_BUFFER_SIZE (16*1024u)
+#define COPY_BUFFER_SIZE (16U*1024U)
+
+/* A safety net for descending recursively into file system trees to copy. On Linux PATH_MAX is 4096, which means the
+ * deepest valid path one can build is around 2048, which we hence use as a safety net here, to not spin endlessly in
+ * case of bind mount cycles and suchlike. */
+#define COPY_DEPTH_MAX 2048U
+
+static ssize_t try_copy_file_range(
+ int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
-static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
- int fd_out, loff_t *off_out,
- size_t len,
- unsigned int flags) {
static int have = -1;
ssize_t r;
- if (have == false)
+ if (have == 0)
return -ENOSYS;
r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
- if (_unlikely_(have < 0))
+ if (have < 0)
have = r >= 0 || errno != ENOSYS;
- if (r >= 0)
- return r;
- else
+ if (r < 0)
return -errno;
+
+ return r;
}
-int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
+enum {
+ FD_IS_NO_PIPE,
+ FD_IS_BLOCKING_PIPE,
+ FD_IS_NONBLOCKING_PIPE,
+};
+
+static int fd_is_nonblock_pipe(int fd) {
+ struct stat st;
+ int flags;
+
+ /* Checks whether the specified file descriptor refers to a pipe, and if so if O_NONBLOCK is set. */
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ if (!S_ISFIFO(st.st_mode))
+ return FD_IS_NO_PIPE;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
+
+ return FLAGS_SET(flags, O_NONBLOCK) ? FD_IS_NONBLOCKING_PIPE : FD_IS_BLOCKING_PIPE;
+}
+
+int copy_bytes_full(
+ int fdf, int fdt,
+ uint64_t max_bytes,
+ CopyFlags copy_flags,
+ void **ret_remains,
+ size_t *ret_remains_size) {
+
bool try_cfr = true, try_sendfile = true, try_splice = true;
- int r;
+ int r, nonblock_pipe = -1;
size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */
assert(fdf >= 0);
assert(fdt >= 0);
- /* Try btrfs reflinks first. */
- if ((copy_flags & COPY_REFLINK) &&
- max_bytes == (uint64_t) -1 &&
- lseek(fdf, 0, SEEK_CUR) == 0 &&
- lseek(fdt, 0, SEEK_CUR) == 0) {
+ /* Tries to copy bytes from the file descriptor 'fdf' to 'fdt' in the smartest possible way. Copies a maximum
+ * of 'max_bytes', which may be specified as UINT64_MAX, in which no maximum is applied. Returns negative on
+ * error, zero if EOF is hit before the bytes limit is hit and positive otherwise. If the copy fails for some
+ * reason but we read but didn't yet write some data an ret_remains/ret_remains_size is not NULL, then it will
+ * be initialized with an allocated buffer containing this "remaining" data. Note that these two parameters are
+ * initialized with a valid buffer only on failure and only if there's actually data already read. Otherwise
+ * these parameters if non-NULL are set to NULL. */
+
+ if (ret_remains)
+ *ret_remains = NULL;
+ if (ret_remains_size)
+ *ret_remains_size = 0;
+
+ /* Try btrfs reflinks first. This only works on regular, seekable files, hence let's check the file offsets of
+ * source and destination first. */
+ if ((copy_flags & COPY_REFLINK)) {
+ off_t foffset;
+
+ foffset = lseek(fdf, 0, SEEK_CUR);
+ if (foffset >= 0) {
+ off_t toffset;
+
+ toffset = lseek(fdt, 0, SEEK_CUR);
+ if (toffset >= 0) {
+
+ if (foffset == 0 && toffset == 0 && max_bytes == UINT64_MAX)
+ r = btrfs_reflink(fdf, fdt); /* full file reflink */
+ else
+ r = btrfs_clone_range(fdf, foffset, fdt, toffset, max_bytes == UINT64_MAX ? 0 : max_bytes); /* partial reflink */
+ if (r >= 0) {
+ off_t t;
+
+ /* This worked, yay! Now — to be fully correct — let's adjust the file pointers */
+ if (max_bytes == UINT64_MAX) {
+
+ /* We cloned to the end of the source file, let's position the read
+ * pointer there, and query it at the same time. */
+ t = lseek(fdf, 0, SEEK_END);
+ if (t < 0)
+ return -errno;
+ if (t < foffset)
+ return -ESPIPE;
+
+ /* Let's adjust the destination file write pointer by the same number
+ * of bytes. */
+ t = lseek(fdt, toffset + (t - foffset), SEEK_SET);
+ if (t < 0)
+ return -errno;
+
+ return 0; /* we copied the whole thing, hence hit EOF, return 0 */
+ } else {
+ t = lseek(fdf, foffset + max_bytes, SEEK_SET);
+ if (t < 0)
+ return -errno;
+
+ t = lseek(fdt, toffset + max_bytes, SEEK_SET);
+ if (t < 0)
+ return -errno;
+
+ return 1; /* we copied only some number of bytes, which worked, but this means we didn't hit EOF, return 1 */
+ }
+ }
- r = btrfs_reflink(fdf, fdt);
- if (r >= 0)
- return 0; /* we copied the whole thing, hence hit EOF, return 0 */
+ log_debug_errno(r, "Reflinking didn't work, falling back to non-reflink copying: %m");
+ }
+ }
}
for (;;) {
ssize_t n;
- if (max_bytes != (uint64_t) -1) {
- if (max_bytes <= 0)
- return 1; /* return > 0 if we hit the max_bytes limit */
+ if (max_bytes <= 0)
+ return 1; /* return > 0 if we hit the max_bytes limit */
- if (m > max_bytes)
- m = max_bytes;
- }
+ if (max_bytes != UINT64_MAX && m > max_bytes)
+ m = max_bytes;
/* First try copy_file_range(), unless we already tried */
if (try_cfr) {
@@ -132,9 +208,51 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
goto next;
}
- /* Then try splice, unless we already tried */
+ /* Then try splice, unless we already tried. */
+ if (try_splice) {
+
+ /* splice()'s asynchronous I/O support is a bit weird. When it encounters a pipe file
+ * descriptor, then it will ignore its O_NONBLOCK flag and instead only honour the
+ * SPLICE_F_NONBLOCK flag specified in its flag parameter. Let's hide this behaviour here, and
+ * check if either of the specified fds are a pipe, and if so, let's pass the flag
+ * automatically, depending on O_NONBLOCK being set.
+ *
+ * Here's a twist though: when we use it to move data between two pipes of which one has
+ * O_NONBLOCK set and the other has not, then we have no individual control over O_NONBLOCK
+ * behaviour. Hence in that case we can't use splice() and still guarantee systematic
+ * O_NONBLOCK behaviour, hence don't. */
+
+ if (nonblock_pipe < 0) {
+ int a, b;
+
+ /* Check if either of these fds is a pipe, and if so non-blocking or not */
+ a = fd_is_nonblock_pipe(fdf);
+ if (a < 0)
+ return a;
+
+ b = fd_is_nonblock_pipe(fdt);
+ if (b < 0)
+ return b;
+
+ if ((a == FD_IS_NO_PIPE && b == FD_IS_NO_PIPE) ||
+ (a == FD_IS_BLOCKING_PIPE && b == FD_IS_NONBLOCKING_PIPE) ||
+ (a == FD_IS_NONBLOCKING_PIPE && b == FD_IS_BLOCKING_PIPE))
+
+ /* splice() only works if one of the fds is a pipe. If neither is, let's skip
+ * this step right-away. As mentioned above, if one of the two fds refers to a
+ * blocking pipe and the other to a non-blocking pipe, we can't use splice()
+ * either, hence don't try either. This hence means we can only use splice() if
+ * either only one of the two fds is a pipe, or if both are pipes with the same
+ * nonblocking flag setting. */
+
+ try_splice = false;
+ else
+ nonblock_pipe = a == FD_IS_NONBLOCKING_PIPE || b == FD_IS_NONBLOCKING_PIPE;
+ }
+ }
+
if (try_splice) {
- n = splice(fdf, NULL, fdt, NULL, m, 0);
+ n = splice(fdf, NULL, fdt, NULL, m, nonblock_pipe ? SPLICE_F_NONBLOCK : 0);
if (n < 0) {
if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
@@ -150,7 +268,8 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
/* As a fallback just copy bits by hand */
{
- uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
+ uint8_t buf[MIN(m, COPY_BUFFER_SIZE)], *p = buf;
+ ssize_t z;
n = read(fdf, buf, sizeof buf);
if (n < 0)
@@ -158,9 +277,34 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
if (n == 0) /* EOF */
break;
- r = loop_write(fdt, buf, (size_t) n, false);
- if (r < 0)
- return r;
+ z = (size_t) n;
+ do {
+ ssize_t k;
+
+ k = write(fdt, p, z);
+ if (k < 0) {
+ r = -errno;
+
+ if (ret_remains) {
+ void *copy;
+
+ copy = memdup(p, z);
+ if (!copy)
+ return -ENOMEM;
+
+ *ret_remains = copy;
+ }
+
+ if (ret_remains_size)
+ *ret_remains_size = z;
+
+ return r;
+ }
+
+ assert(k <= z);
+ z -= k;
+ p += k;
+ } while (z > 0);
}
next:
@@ -336,6 +480,7 @@ static int fd_copy_directory(
int dt,
const char *to,
dev_t original_device,
+ unsigned depth_left,
uid_t override_uid,
gid_t override_gid,
CopyFlags copy_flags) {
@@ -349,6 +494,9 @@ static int fd_copy_directory(
assert(st);
assert(to);
+ if (depth_left == 0)
+ return -ENAMETOOLONG;
+
if (from)
fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
else
@@ -387,13 +535,40 @@ static int fd_copy_directory(
continue;
}
- if (buf.st_dev != original_device)
- continue;
+ if (S_ISDIR(buf.st_mode)) {
+ /*
+ * Don't descend into directories on other file systems, if this is requested. We do a simple
+ * .st_dev check here, which basically comes for free. Note that we do this check only on
+ * directories, not other kind of file system objects, for two reason:
+ *
+ * • The kernel's overlayfs pseudo file system that overlays multiple real file systems
+ * propagates the .st_dev field of the file system a file originates from all the way up
+ * through the stack to stat(). It doesn't do that for directories however. This means that
+ * comparing .st_dev on non-directories suggests that they all are mount points. To avoid
+ * confusion we hence avoid relying on this check for regular files.
+ *
+ * • The main reason we do this check at all is to protect ourselves from bind mount cycles,
+ * where we really want to avoid descending down in all eternity. However the .st_dev check
+ * is usually not sufficient for this protection anyway, as bind mount cycles from the same
+ * file system onto itself can't be detected that way. (Note we also do a recursion depth
+ * check, which is probably the better protection in this regard, which is why
+ * COPY_SAME_MOUNT is optional).
+ */
+
+ if (FLAGS_SET(copy_flags, COPY_SAME_MOUNT)) {
+ if (buf.st_dev != original_device)
+ continue;
+
+ r = fd_is_mount_point(dirfd(d), de->d_name, 0);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ continue;
+ }
- if (S_ISREG(buf.st_mode))
+ q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, depth_left-1, override_uid, override_gid, copy_flags);
+ } else if (S_ISREG(buf.st_mode))
q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
- else if (S_ISDIR(buf.st_mode))
- q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, override_uid, override_gid, copy_flags);
else if (S_ISLNK(buf.st_mode))
q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
else if (S_ISFIFO(buf.st_mode))
@@ -443,7 +618,7 @@ int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t overr
if (S_ISREG(st.st_mode))
return fd_copy_regular(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags);
else if (S_ISDIR(st.st_mode))
- return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, override_uid, override_gid, copy_flags);
+ return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid, override_gid, copy_flags);
else if (S_ISLNK(st.st_mode))
return fd_copy_symlink(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags);
else if (S_ISFIFO(st.st_mode))
@@ -470,7 +645,7 @@ int copy_directory_fd(int dirfd, const char *to, CopyFlags copy_flags) {
if (!S_ISDIR(st.st_mode))
return -ENOTDIR;
- return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, UID_INVALID, GID_INVALID, copy_flags);
+ return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags);
}
int copy_directory(const char *from, const char *to, CopyFlags copy_flags) {
@@ -485,7 +660,7 @@ int copy_directory(const char *from, const char *to, CopyFlags copy_flags) {
if (!S_ISDIR(st.st_mode))
return -ENOTDIR;
- return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, UID_INVALID, GID_INVALID, copy_flags);
+ return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags);
}
int copy_file_fd(const char *from, int fdt, CopyFlags copy_flags) {
@@ -538,31 +713,55 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned
}
int copy_file_atomic(const char *from, const char *to, mode_t mode, unsigned chattr_flags, CopyFlags copy_flags) {
- _cleanup_free_ char *t = NULL;
+ _cleanup_(unlink_and_freep) char *t = NULL;
+ _cleanup_close_ int fdt = -1;
int r;
assert(from);
assert(to);
- r = tempfn_random(to, NULL, &t);
- if (r < 0)
- return r;
+ /* We try to use O_TMPFILE here to create the file if we can. Note that that only works if COPY_REPLACE is not
+ * set though as we need to use linkat() for linking the O_TMPFILE file into the file system but that system
+ * call can't replace existing files. Hence, if COPY_REPLACE is set we create a temporary name in the file
+ * system right-away and unconditionally which we then can renameat() to the right name after we completed
+ * writing it. */
+
+ if (copy_flags & COPY_REPLACE) {
+ r = tempfn_random(to, NULL, &t);
+ if (r < 0)
+ return r;
- r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags, copy_flags);
+ fdt = open(t, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|O_WRONLY|O_CLOEXEC, 0600);
+ if (fdt < 0) {
+ t = mfree(t);
+ return -errno;
+ }
+ } else {
+ fdt = open_tmpfile_linkable(to, O_WRONLY|O_CLOEXEC, &t);
+ if (fdt < 0)
+ return fdt;
+ }
+
+ if (chattr_flags != 0)
+ (void) chattr_fd(fdt, chattr_flags, (unsigned) -1);
+
+ r = copy_file_fd(from, fdt, copy_flags);
if (r < 0)
return r;
+ if (fchmod(fdt, mode) < 0)
+ return -errno;
+
if (copy_flags & COPY_REPLACE) {
- r = renameat(AT_FDCWD, t, AT_FDCWD, to);
+ if (renameat(AT_FDCWD, t, AT_FDCWD, to) < 0)
+ return -errno;
+ } else {
+ r = link_tmpfile(fdt, t, to);
if (r < 0)
- r = -errno;
- } else
- r = rename_noreplace(AT_FDCWD, t, AT_FDCWD, to);
- if (r < 0) {
- (void) unlink(t);
- return r;
+ return r;
}
+ t = mfree(t);
return 0;
}
diff --git a/src/basic/copy.h b/src/basic/copy.h
index 59da4c2425..6a0a6bc9b3 100644
--- a/src/basic/copy.h
+++ b/src/basic/copy.h
@@ -1,34 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
typedef enum CopyFlags {
- COPY_REFLINK = 0x1, /* try to reflink */
- COPY_MERGE = 0x2, /* merge existing trees with our new one to copy */
- COPY_REPLACE = 0x4, /* replace an existing file if there's one */
+ COPY_REFLINK = 1 << 0, /* Try to reflink */
+ COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
+ COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
+ COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
} CopyFlags;
int copy_file_fd(const char *from, int to, CopyFlags copy_flags);
@@ -38,6 +20,9 @@ int copy_tree(const char *from, const char *to, uid_t override_uid, gid_t overri
int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags);
int copy_directory_fd(int dirfd, const char *to, CopyFlags copy_flags);
int copy_directory(const char *from, const char *to, CopyFlags copy_flags);
-int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags);
+int copy_bytes_full(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags, void **ret_remains, size_t *ret_remains_size);
+static inline int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
+ return copy_bytes_full(fdf, fdt, max_bytes, copy_flags, NULL, NULL);
+}
int copy_times(int fdf, int fdt);
int copy_xattr(int fdf, int fdt);
diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c
index 9f0a61a18e..b1c927bcb8 100644
--- a/src/basic/cpu-set-util.c
+++ b/src/basic/cpu-set-util.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
- Copyright 2015 Filipe Brandenburger
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2015 Filipe Brandenburger
***/
#include <errno.h>
@@ -111,10 +95,8 @@ int parse_cpu_set_internal(
}
/* On success, sets *cpu_set and returns ncpus for the system. */
- if (c) {
- *cpu_set = c;
- c = NULL;
- }
+ if (c)
+ *cpu_set = TAKE_PTR(c);
return (int) ncpus;
}
diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h
index c98149eaeb..88470fe15a 100644
--- a/src/basic/cpu-set-util.h
+++ b/src/basic/cpu-set-util.h
@@ -2,23 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
- Copyright 2015 Filipe Brandenburger
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2015 Filipe Brandenburger
***/
#include <sched.h>
diff --git a/src/basic/crypt-util.c b/src/basic/crypt-util.c
index 193cf65dfc..b181ba3ba0 100644
--- a/src/basic/crypt-util.c
+++ b/src/basic/crypt-util.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#if HAVE_LIBCRYPTSETUP
#include "crypt-util.h"
diff --git a/src/basic/crypt-util.h b/src/basic/crypt-util.h
index 537f785607..5b03cb072d 100644
--- a/src/basic/crypt-util.h
+++ b/src/basic/crypt-util.h
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#if HAVE_LIBCRYPTSETUP
#include <libcryptsetup.h>
diff --git a/src/basic/def.h b/src/basic/def.h
index 43e7e17008..4d515c11b6 100644
--- a/src/basic/def.h
+++ b/src/basic/def.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "util.h"
#define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC)
@@ -67,8 +48,10 @@
#define NOTIFY_BUFFER_MAX PIPE_BUF
#if HAVE_SPLIT_USR
-# define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0"
+# define _CONF_PATHS_SPLIT_USR_NULSTR(n) "/lib/" n "\0"
+# define _CONF_PATHS_SPLIT_USR(n) , "/lib/" n
#else
+# define _CONF_PATHS_SPLIT_USR_NULSTR(n)
# define _CONF_PATHS_SPLIT_USR(n)
#endif
@@ -81,6 +64,14 @@
"/run/" n "\0" \
"/usr/local/lib/" n "\0" \
"/usr/lib/" n "\0" \
- _CONF_PATHS_SPLIT_USR(n)
+ _CONF_PATHS_SPLIT_USR_NULSTR(n)
+
+#define CONF_PATHS_STRV(n) \
+ STRV_MAKE( \
+ "/etc/" n, \
+ "/run/" n, \
+ "/usr/local/lib/" n, \
+ "/usr/lib/" n \
+ _CONF_PATHS_SPLIT_USR(n))
#define LONG_LINE_MAX (1U*1024U*1024U)
diff --git a/src/basic/device-nodes.c b/src/basic/device-nodes.c
index 61dc49238c..5fcdf24bd2 100644
--- a/src/basic/device-nodes.c
+++ b/src/basic/device-nodes.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 <errno.h>
#include <stdio.h>
diff --git a/src/basic/device-nodes.h b/src/basic/device-nodes.h
index 49f4ccc729..3840e6d307 100644
--- a/src/basic/device-nodes.h
+++ b/src/basic/device-nodes.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stddef.h>
#include <sys/types.h>
diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c
index e2b093bad3..d1d2c0ef46 100644
--- a/src/basic/dirent-util.c
+++ b/src/basic/dirent-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <sys/stat.h>
diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h
index 94d5ee81a3..b1b87679dc 100644
--- a/src/basic/dirent-util.h
+++ b/src/basic/dirent-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <dirent.h>
#include <errno.h>
#include <stdbool.h>
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
index 0b1d086394..a784a30e1d 100644
--- a/src/basic/env-util.c
+++ b/src/basic/env-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <limits.h>
@@ -84,9 +66,9 @@ bool env_value_is_valid(const char *e) {
if (!utf8_is_valid(e))
return false;
- /* bash allows tabs in environment variables, and so should
- * we */
- if (string_has_cc(e, "\t"))
+ /* bash allows tabs and newlines in environment variables, and so
+ * should we */
+ if (string_has_cc(e, "\t\n"))
return false;
/* POSIX says the overall size of the environment block cannot
@@ -209,11 +191,11 @@ static int env_append(char **r, char ***k, char **a) {
return 0;
}
-char **strv_env_merge(unsigned n_lists, ...) {
+char **strv_env_merge(size_t n_lists, ...) {
size_t n = 0;
char **l, **k, **r;
va_list ap;
- unsigned i;
+ size_t i;
/* Merges an arbitrary number of environment sets */
@@ -288,7 +270,7 @@ static bool env_entry_has_name(const char *entry, const char *name) {
return *t == '=';
}
-char **strv_env_delete(char **x, unsigned n_lists, ...) {
+char **strv_env_delete(char **x, size_t n_lists, ...) {
size_t n, i = 0;
char **k, **r;
va_list ap;
@@ -303,7 +285,7 @@ char **strv_env_delete(char **x, unsigned n_lists, ...) {
return NULL;
STRV_FOREACH(k, x) {
- unsigned v;
+ size_t v;
va_start(ap, n_lists);
for (v = 0; v < n_lists; v++) {
@@ -430,7 +412,8 @@ int strv_env_replace(char ***l, char *p) {
char **strv_env_set(char **x, const char *p) {
- char **k, **r;
+ char **k;
+ _cleanup_strv_free_ char **r = NULL;
char* m[2] = { (char*) p, NULL };
/* Overrides the env var setting of p, returns a new copy */
@@ -441,18 +424,14 @@ char **strv_env_set(char **x, const char *p) {
k = r;
if (env_append(r, &k, x) < 0)
- goto fail;
+ return NULL;
if (env_append(r, &k, m) < 0)
- goto fail;
+ return NULL;
*k = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
+ return TAKE_PTR(r);
}
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
@@ -689,7 +668,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
char **replace_env_argv(char **argv, char **env) {
char **ret, **i;
- unsigned k = 0, l = 0;
+ size_t k = 0, l = 0;
l = strv_length(argv);
@@ -703,7 +682,7 @@ char **replace_env_argv(char **argv, char **env) {
if ((*i)[0] == '$' && !IN_SET((*i)[1], '{', '$')) {
char *e;
char **w, **m = NULL;
- unsigned q;
+ size_t q;
e = strv_env_get(env, *i+1);
if (e) {
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
index 956a2a8270..ef9398e618 100644
--- a/src/basic/env-util.h
+++ b/src/basic/env-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
@@ -50,8 +31,8 @@ char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const cha
bool strv_env_name_is_valid(char **l);
bool strv_env_name_or_assignment_is_valid(char **l);
-char **strv_env_merge(unsigned n_lists, ...);
-char **strv_env_delete(char **x, unsigned n_lists, ...); /* New copy */
+char **strv_env_merge(size_t n_lists, ...);
+char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */
char **strv_env_set(char **x, const char *p); /* New copy ... */
char **strv_env_unset(char **l, const char *p); /* In place ... */
diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c
index 7eb28b8fd1..1b72bbf3ad 100644
--- a/src/basic/errno-list.c
+++ b/src/basic/errno-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
diff --git a/src/basic/errno-list.h b/src/basic/errno-list.h
index 38beaf96dd..9c639b4f55 100644
--- a/src/basic/errno-list.h
+++ b/src/basic/errno-list.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
/*
* MAX_ERRNO is defined as 4095 in linux/err.h
diff --git a/src/basic/escape.c b/src/basic/escape.c
index 7d77aef329..5004763d97 100644
--- a/src/basic/escape.c
+++ b/src/basic/escape.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
@@ -28,8 +10,10 @@
#include "macro.h"
#include "utf8.h"
-size_t cescape_char(char c, char *buf) {
- char * buf_old = buf;
+int cescape_char(char c, char *buf) {
+ char *buf_old = buf;
+
+ /* Needs space for 4 characters in the buffer */
switch (c) {
@@ -201,7 +185,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
/* C++11 style 16bit unicode */
int a[4];
- unsigned i;
+ size_t i;
uint32_t c;
if (length != (size_t) -1 && length < 5)
@@ -228,7 +212,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
/* C++11 style 32bit unicode */
int a[8];
- unsigned i;
+ size_t i;
char32_t c;
if (length != (size_t) -1 && length < 9)
diff --git a/src/basic/escape.h b/src/basic/escape.h
index de89f43a82..2e07c73b9e 100644
--- a/src/basic/escape.h
+++ b/src/basic/escape.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
@@ -58,7 +39,7 @@ typedef enum EscapeStyle {
char *cescape(const char *s);
char *cescape_length(const char *s, size_t n);
-size_t cescape_char(char c, char *buf);
+int cescape_char(char c, char *buf);
int cunescape(const char *s, UnescapeFlags flags, char **ret);
int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
diff --git a/src/basic/ether-addr-util.c b/src/basic/ether-addr-util.c
index bfbd1a4931..461ace73e2 100644
--- a/src/basic/ether-addr-util.c
+++ b/src/basic/ether-addr-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <net/ethernet.h>
@@ -46,19 +28,23 @@ char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR
return buffer;
}
-bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
+int ether_addr_compare(const void *a, const void *b) {
assert(a);
assert(b);
- return a->ether_addr_octet[0] == b->ether_addr_octet[0] &&
- a->ether_addr_octet[1] == b->ether_addr_octet[1] &&
- a->ether_addr_octet[2] == b->ether_addr_octet[2] &&
- a->ether_addr_octet[3] == b->ether_addr_octet[3] &&
- a->ether_addr_octet[4] == b->ether_addr_octet[4] &&
- a->ether_addr_octet[5] == b->ether_addr_octet[5];
+ return memcmp(a, b, ETH_ALEN);
}
-int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset) {
+static void ether_addr_hash_func(const void *p, struct siphash *state) {
+ siphash24_compress(p, sizeof(struct ether_addr), state);
+}
+
+const struct hash_ops ether_addr_hash_ops = {
+ .hash = ether_addr_hash_func,
+ .compare = ether_addr_compare
+};
+
+int ether_addr_from_string(const char *s, struct ether_addr *ret) {
size_t pos = 0, n, field;
char sep = '\0';
const char *hex = HEXDIGITS, *hexoff;
@@ -97,31 +83,35 @@ int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset
assert(s);
assert(ret);
+ s += strspn(s, WHITESPACE);
sep = s[strspn(s, hex)];
- if (sep == '\n')
- return -EINVAL;
- if (!strchr(":.-", sep))
- return -EINVAL;
if (sep == '.') {
uint16_t shorts[3] = { 0 };
parse_fields(shorts);
+ if (s[pos] != '\0')
+ return -EINVAL;
+
for (n = 0; n < ELEMENTSOF(shorts); n++) {
ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8);
ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff);
}
- } else {
- struct ether_addr out = { .ether_addr_octet = { 0 } };
+
+ } else if (IN_SET(sep, ':', '-')) {
+ struct ether_addr out = ETHER_ADDR_NULL;
parse_fields(out.ether_addr_octet);
+ if (s[pos] != '\0')
+ return -EINVAL;
+
for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++)
ret->ether_addr_octet[n] = out.ether_addr_octet[n];
- }
- if (offset)
- *offset = pos;
+ } else
+ return -EINVAL;
+
return 0;
}
diff --git a/src/basic/ether-addr-util.h b/src/basic/ether-addr-util.h
index 08d05a136f..f12f1215d2 100644
--- a/src/basic/ether-addr-util.h
+++ b/src/basic/ether-addr-util.h
@@ -1,35 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/ethernet.h>
#include <stdbool.h>
+#include "hash-funcs.h"
+
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
#define ETHER_ADDR_TO_STRING_MAX (3*6)
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
-bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);
+int ether_addr_compare(const void *a, const void *b);
+static inline bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
+ return ether_addr_compare(a, b) == 0;
+}
#define ETHER_ADDR_NULL ((const struct ether_addr){})
@@ -37,4 +24,6 @@ static inline bool ether_addr_is_null(const struct ether_addr *addr) {
return ether_addr_equal(addr, &ETHER_ADDR_NULL);
}
-int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset);
+int ether_addr_from_string(const char *s, struct ether_addr *ret);
+
+extern const struct hash_ops ether_addr_hash_ops;
diff --git a/src/basic/exec-util.c b/src/basic/exec-util.c
index e0057a7572..7e336f9ce1 100644
--- a/src/basic/exec-util.c
+++ b/src/basic/exec-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -102,7 +84,7 @@ static int do_execute(
* If callbacks is nonnull, execution is serial. Otherwise, we default to parallel.
*/
- r = conf_files_list_strv(&paths, NULL, NULL, CONF_FILES_EXECUTABLE, (const char* const*) directories);
+ r = conf_files_list_strv(&paths, NULL, NULL, CONF_FILES_EXECUTABLE|CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char* const*) directories);
if (r < 0)
return r;
@@ -116,7 +98,7 @@ static int do_execute(
* default action terminating the process, and turn on alarm(). */
if (timeout != USEC_INFINITY)
- alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
+ alarm(DIV_ROUND_UP(timeout, USEC_PER_SEC));
STRV_FOREACH(path, paths) {
_cleanup_free_ char *t = NULL;
diff --git a/src/basic/exec-util.h b/src/basic/exec-util.h
index d69bec7bc2..8b1f18139c 100644
--- a/src/basic/exec-util.h
+++ b/src/basic/exec-util.h
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c
index c02681d4cc..21af8c4c71 100644
--- a/src/basic/exit-status.c
+++ b/src/basic/exit-status.c
@@ -1,25 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <signal.h>
#include <stdlib.h>
+#include <sysexits.h>
#include "exit-status.h"
#include "macro.h"
@@ -27,10 +10,21 @@
const char* exit_status_to_string(int status, ExitStatusLevel level) {
- /* We cast to int here, so that -Wenum doesn't complain that
- * EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */
-
- switch (status) {
+ /* Exit status ranges:
+ *
+ * 0…1 │ ISO C, EXIT_SUCCESS + EXIT_FAILURE
+ * 2…7 │ LSB exit codes for init scripts
+ * 8…63 │ (Currently unmapped)
+ * 64…78 │ BSD defined exit codes
+ * 79…199 │ (Currently unmapped)
+ * 200…241 │ systemd's private error codes (might be extended to 254 in future development)
+ * 242…254 │ (Currently unmapped, but see above)
+ * 255 │ (We should probably stay away from that one, it's frequently used by applications to indicate an
+ * │ exit reason that cannot really be expressed in a single exit status value — such as a propagated
+ * │ signal or such)
+ */
+
+ switch (status) { /* We always cover the ISO C ones */
case EXIT_SUCCESS:
return "SUCCESS";
@@ -39,8 +33,8 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) {
return "FAILURE";
}
- if (IN_SET(level, EXIT_STATUS_SYSTEMD, EXIT_STATUS_LSB)) {
- switch (status) {
+ if (IN_SET(level, EXIT_STATUS_SYSTEMD, EXIT_STATUS_LSB, EXIT_STATUS_FULL)) {
+ switch (status) { /* Optionally we cover our own ones */
case EXIT_CHDIR:
return "CHDIR";
@@ -164,8 +158,8 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) {
}
}
- if (level == EXIT_STATUS_LSB) {
- switch (status) {
+ if (IN_SET(level, EXIT_STATUS_LSB, EXIT_STATUS_FULL)) {
+ switch (status) { /* Optionally we support LSB ones */
case EXIT_INVALIDARGUMENT:
return "INVALIDARGUMENT";
@@ -187,6 +181,56 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) {
}
}
+ if (level == EXIT_STATUS_FULL) {
+ switch (status) { /* Optionally, we support BSD exit statusses */
+
+ case EX_USAGE:
+ return "USAGE";
+
+ case EX_DATAERR:
+ return "DATAERR";
+
+ case EX_NOINPUT:
+ return "NOINPUT";
+
+ case EX_NOUSER:
+ return "NOUSER";
+
+ case EX_NOHOST:
+ return "NOHOST";
+
+ case EX_UNAVAILABLE:
+ return "UNAVAILABLE";
+
+ case EX_SOFTWARE:
+ return "SOFTWARE";
+
+ case EX_OSERR:
+ return "OSERR";
+
+ case EX_OSFILE:
+ return "OSFILE";
+
+ case EX_CANTCREAT:
+ return "CANTCREAT";
+
+ case EX_IOERR:
+ return "IOERR";
+
+ case EX_TEMPFAIL:
+ return "TEMPFAIL";
+
+ case EX_PROTOCOL:
+ return "PROTOCOL";
+
+ case EX_NOPERM:
+ return "NOPERM";
+
+ case EX_CONFIG:
+ return "CONFIG";
+ }
+ }
+
return NULL;
}
@@ -195,7 +239,7 @@ bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success
if (code == CLD_EXITED)
return status == 0 ||
(success_status &&
- set_contains(success_status->status, INT_TO_PTR(status)));
+ set_contains(success_status->status, INT_TO_PTR(status)));
/* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */
if (code == CLD_KILLED)
diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h
index 1e10419f8b..c41e8b82c3 100644
--- a/src/basic/exit-status.h
+++ b/src/basic/exit-status.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "hashmap.h"
@@ -42,10 +23,10 @@ enum {
EXIT_NOTCONFIGURED = 6,
EXIT_NOTRUNNING = 7,
- /* The LSB suggests that error codes >= 200 are "reserved". We
- * use them here under the assumption that they hence are
- * unused by init scripts. */
+ /* BSD's sysexits.h defines a couple EX_xyz exit codes in the range 64 … 78 */
+ /* The LSB suggests that error codes >= 200 are "reserved". We use them here under the assumption that they
+ * hence are unused by init scripts. */
EXIT_CHDIR = 200,
EXIT_NICE,
EXIT_FDS,
@@ -94,7 +75,7 @@ typedef enum ExitStatusLevel {
EXIT_STATUS_MINIMAL, /* only cover libc EXIT_STATUS/EXIT_FAILURE */
EXIT_STATUS_SYSTEMD, /* cover libc and systemd's own exit codes */
EXIT_STATUS_LSB, /* cover libc, systemd's own and LSB exit codes */
- EXIT_STATUS_FULL = EXIT_STATUS_LSB
+ EXIT_STATUS_FULL, /* cover libc, systemd's own, LSB and BSD (EX_xyz) exit codes */
} ExitStatusLevel;
typedef struct ExitStatusSet {
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index 5e42560487..a861b56653 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdarg.h>
@@ -194,8 +176,7 @@ finish:
finish_force_next:
s[sz] = 0;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 1;
}
diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h
index 300c51bb77..8c63b7c306 100644
--- a/src/basic/extract-word.h
+++ b/src/basic/extract-word.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "macro.h"
typedef enum ExtractFlags {
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index 6d7875361c..e085dc23b4 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -25,10 +7,13 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "alloc-util.h"
+#include "copy.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "io-util.h"
#include "macro.h"
#include "memfd-util.h"
#include "missing.h"
@@ -98,8 +83,8 @@ void safe_close_pair(int p[]) {
p[1] = safe_close(p[1]);
}
-void close_many(const int fds[], unsigned n_fd) {
- unsigned i;
+void close_many(const int fds[], size_t n_fd) {
+ size_t i;
assert(fds || n_fd <= 0);
@@ -191,8 +176,8 @@ int fd_cloexec(int fd, bool cloexec) {
return 0;
}
-_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
- unsigned i;
+_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
+ size_t i;
assert(n_fdset == 0 || fdset);
@@ -203,7 +188,7 @@ _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
return false;
}
-int close_all_fds(const int except[], unsigned n_except) {
+int close_all_fds(const int except[], size_t n_except) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
@@ -212,15 +197,22 @@ int close_all_fds(const int except[], unsigned n_except) {
d = opendir("/proc/self/fd");
if (!d) {
- int fd;
struct rlimit rl;
+ int fd, max_fd;
- /* When /proc isn't available (for example in chroots)
- * the fallback is brute forcing through the fd
+ /* When /proc isn't available (for example in chroots) the fallback is brute forcing through the fd
* table */
assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
- for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
+
+ if (rl.rlim_max == 0)
+ return -EINVAL;
+
+ /* Let's take special care if the resource limit is set to unlimited, or actually larger than the range
+ * of 'int'. Let's avoid implicit overflows. */
+ max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1);
+
+ for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
int q;
if (fd_in_set(fd, except, n_except))
@@ -427,7 +419,6 @@ int move_fd(int from, int to, int cloexec) {
int acquire_data_fd(const void *data, size_t size, unsigned flags) {
- char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
_cleanup_close_pair_ int pipefds[2] = { -1, -1 };
char pattern[] = "/dev/shm/data-fd-XXXXXX";
_cleanup_close_ int fd = -1;
@@ -484,10 +475,7 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags) {
if (r < 0)
return r;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
try_pipe:
@@ -524,10 +512,7 @@ try_pipe:
(void) fd_nonblock(pipefds[0], false);
- r = pipefds[0];
- pipefds[0] = -1;
-
- return r;
+ return TAKE_FD(pipefds[0]);
}
try_dev_shm:
@@ -543,12 +528,7 @@ try_dev_shm:
return -EIO;
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
- xsprintf(procfs_path, "/proc/self/fd/%i", fd);
- r = open(procfs_path, O_RDONLY|O_CLOEXEC);
- if (r < 0)
- return -errno;
-
- return r;
+ return fd_reopen(fd, O_RDONLY|O_CLOEXEC);
}
try_dev_shm_without_o_tmpfile:
@@ -580,6 +560,201 @@ try_dev_shm_without_o_tmpfile:
return -EOPNOTSUPP;
}
+/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */
+#define DATA_FD_MEMORY_LIMIT (64U*1024U)
+
+/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */
+#define DATA_FD_TMP_LIMIT (1024U*1024U)
+
+int fd_duplicate_data_fd(int fd) {
+
+ _cleanup_close_ int copy_fd = -1, tmp_fd = -1;
+ _cleanup_free_ void *remains = NULL;
+ size_t remains_size = 0;
+ const char *td;
+ struct stat st;
+ int r;
+
+ /* Creates a 'data' fd from the specified source fd, containing all the same data in a read-only fashion, but
+ * independent of it (i.e. the source fd can be closed and unmounted after this call succeeded). Tries to be
+ * somewhat smart about where to place the data. In the best case uses a memfd(). If memfd() are not supported
+ * uses a pipe instead. For larger data will use an unlinked file in /tmp, and for even larger data one in
+ * /var/tmp. */
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ /* For now, let's only accept regular files, sockets, pipes and char devices */
+ if (S_ISDIR(st.st_mode))
+ return -EISDIR;
+ if (S_ISLNK(st.st_mode))
+ return -ELOOP;
+ if (!S_ISREG(st.st_mode) && !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode) && !S_ISCHR(st.st_mode))
+ return -EBADFD;
+
+ /* If we have reason to believe the data is bounded in size, then let's use memfds or pipes as backing fd. Note
+ * that we use the reported regular file size only as a hint, given that there are plenty special files in
+ * /proc and /sys which report a zero file size but can be read from. */
+
+ if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) {
+
+ /* Try a memfd first */
+ copy_fd = memfd_new("data-fd");
+ if (copy_fd >= 0) {
+ off_t f;
+
+ r = copy_bytes(fd, copy_fd, DATA_FD_MEMORY_LIMIT, 0);
+ if (r < 0)
+ return r;
+
+ f = lseek(copy_fd, 0, SEEK_SET);
+ if (f != 0)
+ return -errno;
+
+ if (r == 0) {
+ /* Did it fit into the limit? If so, we are done. */
+ r = memfd_set_sealed(copy_fd);
+ if (r < 0)
+ return r;
+
+ return TAKE_FD(copy_fd);
+ }
+
+ /* Hmm, pity, this didn't fit. Let's fall back to /tmp then, see below */
+
+ } else {
+ _cleanup_(close_pairp) int pipefds[2] = { -1, -1 };
+ int isz;
+
+ /* If memfds aren't available, use a pipe. Set O_NONBLOCK so that we will get EAGAIN rather
+ * then block indefinitely when we hit the pipe size limit */
+
+ if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
+ return -errno;
+
+ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
+ if (isz < 0)
+ return -errno;
+
+ /* Try to enlarge the pipe size if necessary */
+ if ((size_t) isz < DATA_FD_MEMORY_LIMIT) {
+
+ (void) fcntl(pipefds[1], F_SETPIPE_SZ, DATA_FD_MEMORY_LIMIT);
+
+ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
+ if (isz < 0)
+ return -errno;
+ }
+
+ if ((size_t) isz >= DATA_FD_MEMORY_LIMIT) {
+
+ r = copy_bytes_full(fd, pipefds[1], DATA_FD_MEMORY_LIMIT, 0, &remains, &remains_size);
+ if (r < 0 && r != -EAGAIN)
+ return r; /* If we get EAGAIN it could be because of the source or because of
+ * the destination fd, we can't know, as sendfile() and friends won't
+ * tell us. Hence, treat this as reason to fall back, just to be
+ * sure. */
+ if (r == 0) {
+ /* Everything fit in, yay! */
+ (void) fd_nonblock(pipefds[0], false);
+
+ return TAKE_FD(pipefds[0]);
+ }
+
+ /* Things didn't fit in. But we read data into the pipe, let's remember that, so that
+ * when writing the new file we incorporate this first. */
+ copy_fd = TAKE_FD(pipefds[0]);
+ }
+ }
+ }
+
+ /* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */
+ if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) &&
+ (DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) {
+ off_t f;
+
+ tmp_fd = open_tmpfile_unlinkable(NULL /* NULL as directory means /tmp */, O_RDWR|O_CLOEXEC);
+ if (tmp_fd < 0)
+ return tmp_fd;
+
+ if (copy_fd >= 0) {
+ /* If we tried a memfd/pipe first and it ended up being too large, then copy this into the
+ * temporary file first. */
+
+ r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, 0);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+ }
+
+ if (remains_size > 0) {
+ /* If there were remaining bytes (i.e. read into memory, but not written out yet) from the
+ * failed copy operation, let's flush them out next. */
+
+ r = loop_write(tmp_fd, remains, remains_size, false);
+ if (r < 0)
+ return r;
+ }
+
+ r = copy_bytes(fd, tmp_fd, DATA_FD_TMP_LIMIT - DATA_FD_MEMORY_LIMIT - remains_size, COPY_REFLINK);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ goto finish; /* Yay, it fit in */
+
+ /* It didn't fit in. Let's not forget to use what we already used */
+ f = lseek(tmp_fd, 0, SEEK_SET);
+ if (f != 0)
+ return -errno;
+
+ safe_close(copy_fd);
+ copy_fd = TAKE_FD(tmp_fd);
+
+ remains = mfree(remains);
+ remains_size = 0;
+ }
+
+ /* As last fallback use /var/tmp */
+ r = var_tmp_dir(&td);
+ if (r < 0)
+ return r;
+
+ tmp_fd = open_tmpfile_unlinkable(td, O_RDWR|O_CLOEXEC);
+ if (tmp_fd < 0)
+ return tmp_fd;
+
+ if (copy_fd >= 0) {
+ /* If we tried a memfd/pipe first, or a file in /tmp, and it ended up being too large, than copy this
+ * into the temporary file first. */
+ r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+ }
+
+ if (remains_size > 0) {
+ /* Then, copy in any read but not yet written bytes. */
+ r = loop_write(tmp_fd, remains, remains_size, false);
+ if (r < 0)
+ return r;
+ }
+
+ /* Copy in the rest */
+ r = copy_bytes(fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+
+finish:
+ /* Now convert the O_RDWR file descriptor into an O_RDONLY one (and as side effect seek to the beginning of the
+ * file again */
+
+ return fd_reopen(tmp_fd, O_RDONLY|O_CLOEXEC);
+}
+
int fd_move_above_stdio(int fd) {
int flags, copy;
PROTECT_ERRNO;
@@ -731,3 +906,46 @@ finish:
return r;
}
+
+int fd_reopen(int fd, int flags) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ int new_fd;
+
+ /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to
+ * turn O_RDWR fds into O_RDONLY fds.
+ *
+ * This doesn't work on sockets (since they cannot be open()ed, ever).
+ *
+ * This implicitly resets the file read index to 0. */
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ new_fd = open(procfs_path, flags);
+ if (new_fd < 0)
+ return -errno;
+
+ return new_fd;
+}
+
+int read_nr_open(void) {
+ _cleanup_free_ char *nr_open = NULL;
+ int r;
+
+ /* Returns the kernel's current fd limit, either by reading it of /proc/sys if that works, or using the
+ * hard-coded default compiled-in value of current kernels (1M) if not. This call will never fail. */
+
+ r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m");
+ else {
+ int v;
+
+ r = safe_atoi(nr_open, &v);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open);
+ else
+ return v;
+ }
+
+ /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
+ return 1024 * 1024;
+}
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index c68f482eb2..8adc959da8 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <dirent.h>
#include <stdbool.h>
#include <stdio.h>
@@ -42,7 +23,7 @@ static inline int safe_close_above_stdio(int fd) {
return safe_close(fd);
}
-void close_many(const int fds[], unsigned n_fd);
+void close_many(const int fds[], size_t n_fd);
int fclose_nointr(FILE *f);
FILE* safe_fclose(FILE *f);
@@ -72,7 +53,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec);
-int close_all_fds(const int except[], unsigned n_except);
+int close_all_fds(const int except[], size_t n_except);
int same_fd(int a, int b);
@@ -94,6 +75,8 @@ enum {
int acquire_data_fd(const void *data, size_t size, unsigned flags);
+int fd_duplicate_data_fd(int fd);
+
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
#define ERRNO_IS_DISCONNECT(r) \
IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
@@ -109,3 +92,15 @@ int rearrange_stdio(int original_input_fd, int original_output_fd, int original_
static inline int make_null_stdio(void) {
return rearrange_stdio(-1, -1, -1);
}
+
+/* Like TAKE_PTR() but for file descriptors, resetting them to -1 */
+#define TAKE_FD(fd) \
+ ({ \
+ int _fd_ = (fd); \
+ (fd) = -1; \
+ _fd_; \
+ })
+
+int fd_reopen(int fd, int flags);
+
+int read_nr_open(void);
diff --git a/src/basic/fileio-label.c b/src/basic/fileio-label.c
index b832b6bf04..5f8d8af9af 100644
--- a/src/basic/fileio-label.c
+++ b/src/basic/fileio-label.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Harald Hoyer
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 Harald Hoyer
***/
#include <sys/stat.h>
diff --git a/src/basic/fileio-label.h b/src/basic/fileio-label.h
index 16d095f522..db8e738326 100644
--- a/src/basic/fileio-label.h
+++ b/src/basic/fileio-label.h
@@ -2,23 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Harald Hoyer
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 Harald Hoyer
***/
#include <stdio.h>
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 9875abff51..6b0bad5b71 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -219,6 +201,25 @@ fail:
return 0;
}
+int write_string_filef(
+ const char *fn,
+ WriteStringFileFlags flags,
+ const char *format, ...) {
+
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ va_start(ap, format);
+ r = vasprintf(&p, format, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return write_string_file(fn, p, flags);
+}
+
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -276,29 +277,35 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
}
int read_full_stream(FILE *f, char **contents, size_t *size) {
- size_t n, l;
_cleanup_free_ char *buf = NULL;
struct stat st;
+ size_t n, l;
+ int fd;
assert(f);
assert(contents);
- if (fstat(fileno(f), &st) < 0)
- return -errno;
-
n = LINE_MAX;
- if (S_ISREG(st.st_mode)) {
+ fd = fileno(f);
+ if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's
+ * optimize our buffering) */
- /* Safety check */
- if (st.st_size > READ_FULL_BYTES_MAX)
- return -E2BIG;
+ if (fstat(fileno(f), &st) < 0)
+ return -errno;
+
+ if (S_ISREG(st.st_mode)) {
+
+ /* Safety check */
+ if (st.st_size > READ_FULL_BYTES_MAX)
+ return -E2BIG;
- /* Start with the right file size, but be prepared for files from /proc which generally report a file
- * size of 0. Note that we increase the size to read here by one, so that the first read attempt
- * already makes us notice the EOF. */
- if (st.st_size > 0)
- n = st.st_size + 1;
+ /* Start with the right file size, but be prepared for files from /proc which generally report a file
+ * size of 0. Note that we increase the size to read here by one, so that the first read attempt
+ * already makes us notice the EOF. */
+ if (st.st_size > 0)
+ n = st.st_size + 1;
+ }
}
l = 0;
@@ -335,8 +342,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
}
buf[l] = 0;
- *contents = buf;
- buf = NULL; /* do not free */
+ *contents = TAKE_PTR(buf);
if (size)
*size = l;
@@ -368,11 +374,11 @@ static int parse_env_file_internal(
void *userdata,
int *n_pushed) {
- _cleanup_free_ char *contents = NULL, *key = NULL;
size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
- char *p, *value = NULL;
- int r;
+ _cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL;
unsigned line = 1;
+ char *p;
+ int r;
enum {
PRE_KEY,
@@ -409,10 +415,8 @@ static int parse_env_file_internal(
state = KEY;
last_key_whitespace = (size_t) -1;
- if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
+ return -ENOMEM;
key[n_key++] = c;
}
@@ -432,10 +436,8 @@ static int parse_env_file_internal(
else if (last_key_whitespace == (size_t) -1)
last_key_whitespace = n_key;
- if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
+ return -ENOMEM;
key[n_key++] = c;
}
@@ -457,7 +459,7 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
n_key = 0;
value = NULL;
@@ -472,10 +474,8 @@ static int parse_env_file_internal(
else if (!strchr(WHITESPACE, c)) {
state = VALUE;
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -502,7 +502,7 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
n_key = 0;
value = NULL;
@@ -517,10 +517,8 @@ static int parse_env_file_internal(
else if (last_value_whitespace == (size_t) -1)
last_value_whitespace = n_value;
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -532,10 +530,8 @@ static int parse_env_file_internal(
if (!strchr(newline, c)) {
/* Escaped newlines we eat up entirely */
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -547,10 +543,8 @@ static int parse_env_file_internal(
else if (c == '\\')
state = SINGLE_QUOTE_VALUE_ESCAPE;
else {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -561,10 +555,8 @@ static int parse_env_file_internal(
state = SINGLE_QUOTE_VALUE;
if (!strchr(newline, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -576,10 +568,8 @@ static int parse_env_file_internal(
else if (c == '\\')
state = DOUBLE_QUOTE_VALUE_ESCAPE;
else {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -590,10 +580,8 @@ static int parse_env_file_internal(
state = DOUBLE_QUOTE_VALUE;
if (!strchr(newline, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -638,14 +626,12 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
+
+ value = NULL;
}
return 0;
-
-fail:
- free(value);
- return r;
}
static int check_utf8ness_and_warn(
@@ -710,21 +696,41 @@ static int parse_env_file_push(
return 0;
}
-int parse_env_file(
+int parse_env_filev(
+ FILE *f,
const char *fname,
- const char *newline, ...) {
+ const char *newline,
+ va_list ap) {
- va_list ap;
int r, n_pushed = 0;
+ va_list aq;
if (!newline)
newline = NEWLINE;
+ va_copy(aq, ap);
+ r = parse_env_file_internal(f, fname, newline, parse_env_file_push, &aq, &n_pushed);
+ va_end(aq);
+ if (r < 0)
+ return r;
+
+ return n_pushed;
+}
+
+int parse_env_file(
+ FILE *f,
+ const char *fname,
+ const char *newline,
+ ...) {
+
+ va_list ap;
+ int r;
+
va_start(ap, newline);
- r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap, &n_pushed);
+ r = parse_env_filev(f, fname, newline, ap);
va_end(ap);
- return r < 0 ? r : n_pushed;
+ return r;
}
static int load_env_file_push(
@@ -1242,7 +1248,7 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1283,7 +1289,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
*x = 0;
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1323,7 +1329,7 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
*x = 0;
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1457,8 +1463,7 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
if (fd < 0)
return -errno;
- *ret_path = tmp;
- tmp = NULL;
+ *ret_path = TAKE_PTR(tmp);
return fd;
}
@@ -1544,28 +1549,35 @@ int read_nul_string(FILE *f, char **ret) {
return -ENOMEM;
}
- *ret = x;
- x = NULL;
+ *ret = TAKE_PTR(x);
return 0;
}
int mkdtemp_malloc(const char *template, char **ret) {
- char *p;
+ _cleanup_free_ char *p = NULL;
+ int r;
- assert(template);
assert(ret);
- p = strdup(template);
+ if (template)
+ p = strdup(template);
+ else {
+ const char *tmp;
+
+ r = tmp_dir(&tmp);
+ if (r < 0)
+ return r;
+
+ p = strjoin(tmp, "/XXXXXX");
+ }
if (!p)
return -ENOMEM;
- if (!mkdtemp(p)) {
- free(p);
+ if (!mkdtemp(p))
return -errno;
- }
- *ret = p;
+ *ret = TAKE_PTR(p);
return 0;
}
@@ -1634,8 +1646,7 @@ int read_line(FILE *f, size_t limit, char **ret) {
if (ret) {
buffer[n] = 0;
- *ret = buffer;
- buffer = NULL;
+ *ret = TAKE_PTR(buffer);
}
return (int) count;
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index da5d5c66b5..77e6206e95 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <dirent.h>
#include <stdbool.h>
#include <stddef.h>
@@ -30,12 +11,12 @@
#include "time-util.h"
typedef enum {
- WRITE_STRING_FILE_CREATE = 1<<0,
- WRITE_STRING_FILE_ATOMIC = 1<<1,
- WRITE_STRING_FILE_AVOID_NEWLINE = 1<<2,
- WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1<<3,
- WRITE_STRING_FILE_SYNC = 1<<4,
- WRITE_STRING_FILE_DISABLE_BUFFER = 1<<5,
+ WRITE_STRING_FILE_CREATE = 1 << 0,
+ WRITE_STRING_FILE_ATOMIC = 1 << 1,
+ WRITE_STRING_FILE_AVOID_NEWLINE = 1 << 2,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 3,
+ WRITE_STRING_FILE_SYNC = 1 << 4,
+ WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5,
/* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one
more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()
@@ -52,13 +33,16 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin
return write_string_file_ts(fn, line, flags, NULL);
}
+int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
+
int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
int read_full_stream(FILE *f, char **contents, size_t *size);
int verify_file(const char *fn, const char *blob, bool accept_extra_nl);
-int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
+int parse_env_filev(FILE *f, const char *fname, const char *separator, va_list ap);
+int parse_env_file(FILE *f, const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l);
diff --git a/src/basic/format-table.c b/src/basic/format-table.c
new file mode 100644
index 0000000000..94e796d1ca
--- /dev/null
+++ b/src/basic/format-table.c
@@ -0,0 +1,1247 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdio_ext.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "format-table.h"
+#include "gunicode.h"
+#include "pager.h"
+#include "parse-util.h"
+#include "string-util.h"
+#include "terminal-util.h"
+#include "time-util.h"
+#include "utf8.h"
+#include "util.h"
+
+#define DEFAULT_WEIGHT 100
+
+/*
+ A few notes on implementation details:
+
+ - TableCell is a 'fake' structure, it's just used as data type to pass references to specific cell positions in the
+ table. It can be easily converted to an index number and back.
+
+ - TableData is where the actual data is stored: it encapsulates the data and formatting for a specific cell. It's
+ 'pseudo-immutable' and ref-counted. When a cell's data's formatting is to be changed, we duplicate the object if the
+ ref-counting is larger than 1. Note that TableData and its ref-counting is mostly not visible to the outside. The
+ outside only sees Table and TableCell.
+
+ - The Table object stores a simple one-dimensional array of references to TableData objects, one row after the
+ previous one.
+
+ - There's no special concept of a "row" or "column" in the table, and no special concept of the "header" row. It's all
+ derived from the cell index: we know how many cells are to be stored in a row, and can determine the rest from
+ that. The first row is always the header row. If header display is turned off we simply skip outputting the first
+ row. Also, when sorting rows we always leave the first row where it is, as the header shouldn't move.
+
+ - Note because there's no row and no column object some properties that might be approproate as row/column properties
+ are exposed as cell properties instead. For example, the "weight" of a column (which is used to determine where to
+ add/remove space preferable when expanding/compressing tables horizontally) is actually made the "weight" of a
+ cell. Given that we usually need it per-column though we will calculate the average across every cell of the column
+ instead.
+
+ - To make things easy, when cells are added without any explicit configured formatting, then we'll copy the formatting
+ from the same cell in the previous cell. This is particularly useful for the "weight" of the cell (see above), as
+ this means setting the weight of the cells of the header row will nicely propagate to all cells in the other rows.
+*/
+
+typedef struct TableData {
+ unsigned n_ref;
+ TableDataType type;
+
+ size_t minimum_width; /* minimum width for the column */
+ size_t maximum_width; /* maximum width for the column */
+ unsigned weight; /* the horizontal weight for this column, in case the table is expanded/compressed */
+ unsigned ellipsize_percent; /* 0 … 100, where to place the ellipsis when compression is needed */
+ unsigned align_percent; /* 0 … 100, where to pad with spaces when expanding is needed. 0: left-aligned, 100: right-aligned */
+
+ const char *color; /* ANSI color string to use for this cell. When written to terminal should not move cursor. Will automatically be reset after the cell */
+ char *formatted; /* A cached textual representation of the cell data, before ellipsation/alignment */
+
+ union {
+ uint8_t data[0]; /* data is generic array */
+ bool boolean;
+ usec_t timestamp;
+ usec_t timespan;
+ uint64_t size;
+ char string[0];
+ uint32_t uint32;
+ /* … add more here as we start supporting more cell data types … */
+ };
+} TableData;
+
+static size_t TABLE_CELL_TO_INDEX(TableCell *cell) {
+ unsigned i;
+
+ assert(cell);
+
+ i = PTR_TO_UINT(cell);
+ assert(i > 0);
+
+ return i-1;
+}
+
+static TableCell* TABLE_INDEX_TO_CELL(size_t index) {
+ assert(index != (size_t) -1);
+ return UINT_TO_PTR((unsigned) (index + 1));
+}
+
+struct Table {
+ size_t n_columns;
+ size_t n_cells;
+
+ bool header; /* Whether to show the header row? */
+ size_t width; /* If != (size_t) -1 the width to format this table in */
+
+ TableData **data;
+ size_t n_allocated;
+
+ size_t *display_map; /* List of columns to show (by their index). It's fine if columns are listed multiple times or not at all */
+ size_t n_display_map;
+
+ size_t *sort_map; /* The columns to order rows by, in order of preference. */
+ size_t n_sort_map;
+};
+
+Table *table_new_raw(size_t n_columns) {
+ _cleanup_(table_unrefp) Table *t = NULL;
+
+ assert(n_columns > 0);
+
+ t = new(Table, 1);
+ if (!t)
+ return NULL;
+
+ *t = (struct Table) {
+ .n_columns = n_columns,
+ .header = true,
+ .width = (size_t) -1,
+ };
+
+ return TAKE_PTR(t);
+}
+
+Table *table_new_internal(const char *first_header, ...) {
+ _cleanup_(table_unrefp) Table *t = NULL;
+ size_t n_columns = 1;
+ va_list ap;
+ int r;
+
+ assert(first_header);
+
+ va_start(ap, first_header);
+ for (;;) {
+ const char *h;
+
+ h = va_arg(ap, const char*);
+ if (!h)
+ break;
+
+ n_columns++;
+ }
+ va_end(ap);
+
+ t = table_new_raw(n_columns);
+ if (!t)
+ return NULL;
+
+ r = table_add_cell(t, NULL, TABLE_STRING, first_header);
+ if (r < 0)
+ return NULL;
+
+ va_start(ap, first_header);
+ for (;;) {
+ const char *h;
+
+ h = va_arg(ap, const char*);
+ if (!h)
+ break;
+
+ r = table_add_cell(t, NULL, TABLE_STRING, h);
+ if (r < 0) {
+ va_end(ap);
+ return NULL;
+ }
+ }
+ va_end(ap);
+
+ assert(t->n_columns == t->n_cells);
+ return TAKE_PTR(t);
+}
+
+static TableData *table_data_unref(TableData *d) {
+ if (!d)
+ return NULL;
+
+ assert(d->n_ref > 0);
+ d->n_ref--;
+
+ if (d->n_ref > 0)
+ return NULL;
+
+ free(d->formatted);
+ return mfree(d);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(TableData*, table_data_unref);
+
+static TableData *table_data_ref(TableData *d) {
+ if (!d)
+ return NULL;
+
+ assert(d->n_ref > 0);
+ d->n_ref++;
+
+ return d;
+}
+
+Table *table_unref(Table *t) {
+ size_t i;
+
+ if (!t)
+ return NULL;
+
+ for (i = 0; i < t->n_cells; i++)
+ table_data_unref(t->data[i]);
+
+ free(t->data);
+ free(t->display_map);
+ free(t->sort_map);
+
+ return mfree(t);
+}
+
+static size_t table_data_size(TableDataType type, const void *data) {
+
+ switch (type) {
+
+ case TABLE_EMPTY:
+ return 0;
+
+ case TABLE_STRING:
+ return strlen(data) + 1;
+
+ case TABLE_BOOLEAN:
+ return sizeof(bool);
+
+ case TABLE_TIMESTAMP:
+ case TABLE_TIMESPAN:
+ return sizeof(usec_t);
+
+ case TABLE_SIZE:
+ return sizeof(uint64_t);
+
+ case TABLE_UINT32:
+ return sizeof(uint32_t);
+
+ default:
+ assert_not_reached("Uh? Unexpected cell type");
+ }
+}
+
+static bool table_data_matches(
+ TableData *d,
+ TableDataType type,
+ const void *data,
+ size_t minimum_width,
+ size_t maximum_width,
+ unsigned weight,
+ unsigned align_percent,
+ unsigned ellipsize_percent) {
+
+ size_t k, l;
+ assert(d);
+
+ if (d->type != type)
+ return false;
+
+ if (d->minimum_width != minimum_width)
+ return false;
+
+ if (d->maximum_width != maximum_width)
+ return false;
+
+ if (d->weight != weight)
+ return false;
+
+ if (d->align_percent != align_percent)
+ return false;
+
+ if (d->ellipsize_percent != ellipsize_percent)
+ return false;
+
+ k = table_data_size(type, data);
+ l = table_data_size(d->type, d->data);
+
+ if (k != l)
+ return false;
+
+ return memcmp(data, d->data, l) == 0;
+}
+
+static TableData *table_data_new(
+ TableDataType type,
+ const void *data,
+ size_t minimum_width,
+ size_t maximum_width,
+ unsigned weight,
+ unsigned align_percent,
+ unsigned ellipsize_percent) {
+
+ size_t data_size;
+ TableData *d;
+
+ data_size = table_data_size(type, data);
+
+ d = malloc0(offsetof(TableData, data) + data_size);
+ if (!d)
+ return NULL;
+
+ d->n_ref = 1;
+ d->type = type;
+ d->minimum_width = minimum_width;
+ d->maximum_width = maximum_width;
+ d->weight = weight;
+ d->align_percent = align_percent;
+ d->ellipsize_percent = ellipsize_percent;
+ memcpy_safe(d->data, data, data_size);
+
+ return d;
+}
+
+int table_add_cell_full(
+ Table *t,
+ TableCell **ret_cell,
+ TableDataType type,
+ const void *data,
+ size_t minimum_width,
+ size_t maximum_width,
+ unsigned weight,
+ unsigned align_percent,
+ unsigned ellipsize_percent) {
+
+ _cleanup_(table_data_unrefp) TableData *d = NULL;
+ TableData *p;
+
+ assert(t);
+ assert(type >= 0);
+ assert(type < _TABLE_DATA_TYPE_MAX);
+
+ /* Determine the cell adjacent to the current one, but one row up */
+ if (t->n_cells >= t->n_columns)
+ assert_se(p = t->data[t->n_cells - t->n_columns]);
+ else
+ p = NULL;
+
+ /* If formatting parameters are left unspecified, copy from the previous row */
+ if (minimum_width == (size_t) -1)
+ minimum_width = p ? p->minimum_width : 1;
+
+ if (weight == (unsigned) -1)
+ weight = p ? p->weight : DEFAULT_WEIGHT;
+
+ if (align_percent == (unsigned) -1)
+ align_percent = p ? p->align_percent : 0;
+
+ if (ellipsize_percent == (unsigned) -1)
+ ellipsize_percent = p ? p->ellipsize_percent : 100;
+
+ assert(align_percent <= 100);
+ assert(ellipsize_percent <= 100);
+
+ /* Small optimization: Pretty often adjacent cells in two subsequent lines have the same data and
+ * formatting. Let's see if we can reuse the cell data and ref it once more. */
+
+ if (p && table_data_matches(p, type, data, minimum_width, maximum_width, weight, align_percent, ellipsize_percent))
+ d = table_data_ref(p);
+ else {
+ d = table_data_new(type, data, minimum_width, maximum_width, weight, align_percent, ellipsize_percent);
+ if (!d)
+ return -ENOMEM;
+ }
+
+ if (!GREEDY_REALLOC(t->data, t->n_allocated, MAX(t->n_cells + 1, t->n_columns)))
+ return -ENOMEM;
+
+ if (ret_cell)
+ *ret_cell = TABLE_INDEX_TO_CELL(t->n_cells);
+
+ t->data[t->n_cells++] = TAKE_PTR(d);
+
+ return 0;
+}
+
+int table_dup_cell(Table *t, TableCell *cell) {
+ size_t i;
+
+ assert(t);
+
+ /* Add the data of the specified cell a second time as a new cell to the end. */
+
+ i = TABLE_CELL_TO_INDEX(cell);
+ if (i >= t->n_cells)
+ return -ENXIO;
+
+ if (!GREEDY_REALLOC(t->data, t->n_allocated, MAX(t->n_cells + 1, t->n_columns)))
+ return -ENOMEM;
+
+ t->data[t->n_cells++] = table_data_ref(t->data[i]);
+ return 0;
+}
+
+static int table_dedup_cell(Table *t, TableCell *cell) {
+ TableData *nd, *od;
+ size_t i;
+
+ assert(t);
+
+ /* Helper call that ensures the specified cell's data object has a ref count of 1, which we can use before
+ * changing a cell's formatting without effecting every other cell's formatting that shares the same data */
+
+ i = TABLE_CELL_TO_INDEX(cell);
+ if (i >= t->n_cells)
+ return -ENXIO;
+
+ assert_se(od = t->data[i]);
+ if (od->n_ref == 1)
+ return 0;
+
+ assert(od->n_ref > 1);
+
+ nd = table_data_new(od->type, od->data, od->minimum_width, od->maximum_width, od->weight, od->align_percent, od->ellipsize_percent);
+ if (!nd)
+ return -ENOMEM;
+
+ table_data_unref(od);
+ t->data[i] = nd;
+
+ assert(nd->n_ref == 1);
+
+ return 1;
+}
+
+static TableData *table_get_data(Table *t, TableCell *cell) {
+ size_t i;
+
+ assert(t);
+ assert(cell);
+
+ /* Get the data object of the specified cell, or NULL if it doesn't exist */
+
+ i = TABLE_CELL_TO_INDEX(cell);
+ if (i >= t->n_cells)
+ return NULL;
+
+ assert(t->data[i]);
+ assert(t->data[i]->n_ref > 0);
+
+ return t->data[i];
+}
+
+int table_set_minimum_width(Table *t, TableCell *cell, size_t minimum_width) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ if (minimum_width == (size_t) -1)
+ minimum_width = 1;
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->minimum_width = minimum_width;
+ return 0;
+}
+
+int table_set_maximum_width(Table *t, TableCell *cell, size_t maximum_width) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->maximum_width = maximum_width;
+ return 0;
+}
+
+int table_set_weight(Table *t, TableCell *cell, unsigned weight) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ if (weight == (unsigned) -1)
+ weight = DEFAULT_WEIGHT;
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->weight = weight;
+ return 0;
+}
+
+int table_set_align_percent(Table *t, TableCell *cell, unsigned percent) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ if (percent == (unsigned) -1)
+ percent = 0;
+
+ assert(percent <= 100);
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->align_percent = percent;
+ return 0;
+}
+
+int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ if (percent == (unsigned) -1)
+ percent = 100;
+
+ assert(percent <= 100);
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->ellipsize_percent = percent;
+ return 0;
+}
+
+int table_set_color(Table *t, TableCell *cell, const char *color) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->color = empty_to_null(color);
+ return 0;
+}
+
+int table_add_many_internal(Table *t, TableDataType first_type, ...) {
+ TableDataType type;
+ va_list ap;
+ int r;
+
+ assert(t);
+ assert(first_type >= 0);
+ assert(first_type < _TABLE_DATA_TYPE_MAX);
+
+ type = first_type;
+
+ va_start(ap, first_type);
+ for (;;) {
+ const void *data;
+ union {
+ uint64_t size;
+ usec_t usec;
+ uint32_t uint32;
+ bool b;
+ } buffer;
+
+ switch (type) {
+
+ case TABLE_EMPTY:
+ data = NULL;
+ break;
+
+ case TABLE_STRING:
+ data = va_arg(ap, const char *);
+ break;
+
+ case TABLE_BOOLEAN:
+ buffer.b = va_arg(ap, int);
+ data = &buffer.b;
+ break;
+
+ case TABLE_TIMESTAMP:
+ case TABLE_TIMESPAN:
+ buffer.usec = va_arg(ap, usec_t);
+ data = &buffer.usec;
+ break;
+
+ case TABLE_SIZE:
+ buffer.size = va_arg(ap, uint64_t);
+ data = &buffer.size;
+ break;
+
+ case TABLE_UINT32:
+ buffer.uint32 = va_arg(ap, uint32_t);
+ data = &buffer.uint32;
+ break;
+
+ case _TABLE_DATA_TYPE_MAX:
+ /* Used as end marker */
+ va_end(ap);
+ return 0;
+
+ default:
+ assert_not_reached("Uh? Unexpected data type.");
+ }
+
+ r = table_add_cell(t, NULL, type, data);
+ if (r < 0) {
+ va_end(ap);
+ return r;
+ }
+
+ type = va_arg(ap, TableDataType);
+ }
+}
+
+void table_set_header(Table *t, bool b) {
+ assert(t);
+
+ t->header = b;
+}
+
+void table_set_width(Table *t, size_t width) {
+ assert(t);
+
+ t->width = width;
+}
+
+int table_set_display(Table *t, size_t first_column, ...) {
+ size_t allocated, column;
+ va_list ap;
+
+ assert(t);
+
+ allocated = t->n_display_map;
+ column = first_column;
+
+ va_start(ap, first_column);
+ for (;;) {
+ assert(column < t->n_columns);
+
+ if (!GREEDY_REALLOC(t->display_map, allocated, MAX(t->n_columns, t->n_display_map+1))) {
+ va_end(ap);
+ return -ENOMEM;
+ }
+
+ t->display_map[t->n_display_map++] = column;
+
+ column = va_arg(ap, size_t);
+ if (column == (size_t) -1)
+ break;
+
+ }
+ va_end(ap);
+
+ return 0;
+}
+
+int table_set_sort(Table *t, size_t first_column, ...) {
+ size_t allocated, column;
+ va_list ap;
+
+ assert(t);
+
+ allocated = t->n_sort_map;
+ column = first_column;
+
+ va_start(ap, first_column);
+ for (;;) {
+ assert(column < t->n_columns);
+
+ if (!GREEDY_REALLOC(t->sort_map, allocated, MAX(t->n_columns, t->n_sort_map+1))) {
+ va_end(ap);
+ return -ENOMEM;
+ }
+
+ t->sort_map[t->n_sort_map++] = column;
+
+ column = va_arg(ap, size_t);
+ if (column == (size_t) -1)
+ break;
+ }
+ va_end(ap);
+
+ return 0;
+}
+
+static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t index_b) {
+ assert(a);
+ assert(b);
+
+ if (a->type == b->type) {
+
+ /* We only define ordering for cells of the same data type. If cells with different data types are
+ * compared we follow the order the cells were originally added in */
+
+ switch (a->type) {
+
+ case TABLE_STRING:
+ return strcmp(a->string, b->string);
+
+ case TABLE_BOOLEAN:
+ if (!a->boolean && b->boolean)
+ return -1;
+ if (a->boolean && !b->boolean)
+ return 1;
+ return 0;
+
+ case TABLE_TIMESTAMP:
+ if (a->timestamp < b->timestamp)
+ return -1;
+ if (a->timestamp > b->timestamp)
+ return 1;
+ return 0;
+
+ case TABLE_TIMESPAN:
+ if (a->timespan < b->timespan)
+ return -1;
+ if (a->timespan > b->timespan)
+ return 1;
+ return 0;
+
+ case TABLE_SIZE:
+ if (a->size < b->size)
+ return -1;
+ if (a->size > b->size)
+ return 1;
+ return 0;
+
+ case TABLE_UINT32:
+ if (a->uint32 < b->uint32)
+ return -1;
+ if (a->uint32 > b->uint32)
+ return 1;
+ return 0;
+
+ default:
+ ;
+ }
+ }
+
+ /* Generic fallback using the orginal order in which the cells where added. */
+ if (index_a < index_b)
+ return -1;
+ if (index_a > index_b)
+ return 1;
+
+ return 0;
+}
+
+static int table_data_compare(const void *x, const void *y, void *userdata) {
+ const size_t *a = x, *b = y;
+ Table *t = userdata;
+ size_t i;
+ int r;
+
+ assert(t);
+ assert(t->sort_map);
+
+ /* Make sure the header stays at the beginning */
+ if (*a < t->n_columns && *b < t->n_columns)
+ return 0;
+ if (*a < t->n_columns)
+ return -1;
+ if (*b < t->n_columns)
+ return 1;
+
+ /* Order other lines by the sorting map */
+ for (i = 0; i < t->n_sort_map; i++) {
+ TableData *d, *dd;
+
+ d = t->data[*a + t->sort_map[i]];
+ dd = t->data[*b + t->sort_map[i]];
+
+ r = cell_data_compare(d, *a, dd, *b);
+ if (r != 0)
+ return r;
+ }
+
+ /* Order identical lines by the order there were originally added in */
+ if (*a < *b)
+ return -1;
+ if (*a > *b)
+ return 1;
+
+ return 0;
+}
+
+static const char *table_data_format(TableData *d) {
+ assert(d);
+
+ if (d->formatted)
+ return d->formatted;
+
+ switch (d->type) {
+ case TABLE_EMPTY:
+ return "";
+
+ case TABLE_STRING:
+ return d->string;
+
+ case TABLE_BOOLEAN:
+ return yes_no(d->boolean);
+
+ case TABLE_TIMESTAMP: {
+ _cleanup_free_ char *p;
+
+ p = new(char, FORMAT_TIMESTAMP_MAX);
+ if (!p)
+ return NULL;
+
+ if (!format_timestamp(p, FORMAT_TIMESTAMP_MAX, d->timestamp))
+ return "n/a";
+
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_TIMESPAN: {
+ _cleanup_free_ char *p;
+
+ p = new(char, FORMAT_TIMESPAN_MAX);
+ if (!p)
+ return NULL;
+
+ if (!format_timespan(p, FORMAT_TIMESPAN_MAX, d->timestamp, 0))
+ return "n/a";
+
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_SIZE: {
+ _cleanup_free_ char *p;
+
+ p = new(char, FORMAT_BYTES_MAX);
+ if (!p)
+ return NULL;
+
+ if (!format_bytes(p, FORMAT_BYTES_MAX, d->size))
+ return "n/a";
+
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_UINT32: {
+ _cleanup_free_ char *p;
+
+ p = new(char, DECIMAL_STR_WIDTH(d->uint32) + 1);
+ if (!p)
+ return NULL;
+
+ sprintf(p, "%" PRIu32, d->uint32);
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ default:
+ assert_not_reached("Unexpected type?");
+ }
+
+ return d->formatted;
+}
+
+static int table_data_requested_width(TableData *d, size_t *ret) {
+ const char *t;
+ size_t l;
+
+ t = table_data_format(d);
+ if (!t)
+ return -ENOMEM;
+
+ l = utf8_console_width(t);
+ if (l == (size_t) -1)
+ return -EINVAL;
+
+ if (d->maximum_width != (size_t) -1 && l > d->maximum_width)
+ l = d->maximum_width;
+
+ if (l < d->minimum_width)
+ l = d->minimum_width;
+
+ *ret = l;
+ return 0;
+}
+
+static char *align_string_mem(const char *str, size_t new_length, unsigned percent) {
+ size_t w = 0, space, lspace, old_length;
+ const char *p;
+ char *ret;
+ size_t i;
+
+ /* As with ellipsize_mem(), 'old_length' is a byte size while 'new_length' is a width in character cells */
+
+ assert(str);
+ assert(percent <= 100);
+
+ old_length = strlen(str);
+
+ /* Determine current width on screen */
+ p = str;
+ while (p < str + old_length) {
+ char32_t c;
+
+ if (utf8_encoded_to_unichar(p, &c) < 0) {
+ p++, w++; /* count invalid chars as 1 */
+ continue;
+ }
+
+ p = utf8_next_char(p);
+ w += unichar_iswide(c) ? 2 : 1;
+ }
+
+ /* Already wider than the target, if so, don't do anything */
+ if (w >= new_length)
+ return strndup(str, old_length);
+
+ /* How much spaces shall we add? An how much on the left side? */
+ space = new_length - w;
+ lspace = space * percent / 100U;
+
+ ret = new(char, space + old_length + 1);
+ if (!ret)
+ return NULL;
+
+ for (i = 0; i < lspace; i++)
+ ret[i] = ' ';
+ memcpy(ret + lspace, str, old_length);
+ for (i = lspace + old_length; i < space + old_length; i++)
+ ret[i] = ' ';
+
+ ret[space + old_length] = 0;
+ return ret;
+}
+
+int table_print(Table *t, FILE *f) {
+ size_t n_rows, *minimum_width, *maximum_width, display_columns, *requested_width,
+ i, j, table_minimum_width, table_maximum_width, table_requested_width, table_effective_width,
+ *width;
+ _cleanup_free_ size_t *sorted = NULL;
+ uint64_t *column_weight, weight_sum;
+ int r;
+
+ assert(t);
+
+ if (!f)
+ f = stdout;
+
+ /* Ensure we have no incomplete rows */
+ assert(t->n_cells % t->n_columns == 0);
+
+ n_rows = t->n_cells / t->n_columns;
+ assert(n_rows > 0); /* at least the header row must be complete */
+
+ if (t->sort_map) {
+ /* If sorting is requested, let's calculate an index table we use to lookup the actual index to display with. */
+
+ sorted = new(size_t, n_rows);
+ if (!sorted)
+ return -ENOMEM;
+
+ for (i = 0; i < n_rows; i++)
+ sorted[i] = i * t->n_columns;
+
+ qsort_r_safe(sorted, n_rows, sizeof(size_t), table_data_compare, t);
+ }
+
+ if (t->display_map)
+ display_columns = t->n_display_map;
+ else
+ display_columns = t->n_columns;
+
+ assert(display_columns > 0);
+
+ minimum_width = newa(size_t, display_columns);
+ maximum_width = newa(size_t, display_columns);
+ requested_width = newa(size_t, display_columns);
+ width = newa(size_t, display_columns);
+ column_weight = newa0(uint64_t, display_columns);
+
+ for (j = 0; j < display_columns; j++) {
+ minimum_width[j] = 1;
+ maximum_width[j] = (size_t) -1;
+ requested_width[j] = (size_t) -1;
+ }
+
+ /* First pass: determine column sizes */
+ for (i = t->header ? 0 : 1; i < n_rows; i++) {
+ TableData **row;
+
+ /* Note that we don't care about ordering at this time, as we just want to determine column sizes,
+ * hence we don't care for sorted[] during the first pass. */
+ row = t->data + i * t->n_columns;
+
+ for (j = 0; j < display_columns; j++) {
+ TableData *d;
+ size_t req;
+
+ assert_se(d = row[t->display_map ? t->display_map[j] : j]);
+
+ r = table_data_requested_width(d, &req);
+ if (r < 0)
+ return r;
+
+ /* Determine the biggest width that any cell in this column would like to have */
+ if (requested_width[j] == (size_t) -1 ||
+ requested_width[j] < req)
+ requested_width[j] = req;
+
+ /* Determine the minimum width any cell in this column needs */
+ if (minimum_width[j] < d->minimum_width)
+ minimum_width[j] = d->minimum_width;
+
+ /* Determine the maximum width any cell in this column needs */
+ if (d->maximum_width != (size_t) -1 &&
+ (maximum_width[j] == (size_t) -1 ||
+ maximum_width[j] > d->maximum_width))
+ maximum_width[j] = d->maximum_width;
+
+ /* Determine the full columns weight */
+ column_weight[j] += d->weight;
+ }
+ }
+
+ /* One space between each column */
+ table_requested_width = table_minimum_width = table_maximum_width = display_columns - 1;
+
+ /* Calculate the total weight for all columns, plus the minimum, maximum and requested width for the table. */
+ weight_sum = 0;
+ for (j = 0; j < display_columns; j++) {
+ weight_sum += column_weight[j];
+
+ table_minimum_width += minimum_width[j];
+
+ if (maximum_width[j] == (size_t) -1)
+ table_maximum_width = (size_t) -1;
+ else
+ table_maximum_width += maximum_width[j];
+
+ table_requested_width += requested_width[j];
+ }
+
+ /* Calculate effective table width */
+ if (t->width == (size_t) -1)
+ table_effective_width = pager_have() ? table_requested_width : MIN(table_requested_width, columns());
+ else
+ table_effective_width = t->width;
+
+ if (table_maximum_width != (size_t) -1 && table_effective_width > table_maximum_width)
+ table_effective_width = table_maximum_width;
+
+ if (table_effective_width < table_minimum_width)
+ table_effective_width = table_minimum_width;
+
+ if (table_effective_width >= table_requested_width) {
+ size_t extra;
+
+ /* We have extra room, let's distribute it among columns according to their weights. We first provide
+ * each column with what it asked for and the distribute the rest. */
+
+ extra = table_effective_width - table_requested_width;
+
+ for (j = 0; j < display_columns; j++) {
+ size_t delta;
+
+ if (weight_sum == 0)
+ width[j] = requested_width[j] + extra / (display_columns - j); /* Avoid division by zero */
+ else
+ width[j] = requested_width[j] + (extra * column_weight[j]) / weight_sum;
+
+ if (maximum_width[j] != (size_t) -1 && width[j] > maximum_width[j])
+ width[j] = maximum_width[j];
+
+ if (width[j] < minimum_width[j])
+ width[j] = minimum_width[j];
+
+ assert(width[j] >= requested_width[j]);
+ delta = width[j] - requested_width[j];
+
+ /* Subtract what we just added from the rest */
+ if (extra > delta)
+ extra -= delta;
+ else
+ extra = 0;
+
+ assert(weight_sum >= column_weight[j]);
+ weight_sum -= column_weight[j];
+ }
+
+ } else {
+ /* We need to compress the table, columns can't get what they asked for. We first provide each column
+ * with the minimum they need, and then distribute anything left. */
+ bool finalize = false;
+ size_t extra;
+
+ extra = table_effective_width - table_minimum_width;
+
+ for (j = 0; j < display_columns; j++)
+ width[j] = (size_t) -1;
+
+ for (;;) {
+ bool restart = false;
+
+ for (j = 0; j < display_columns; j++) {
+ size_t delta, w;
+
+ /* Did this column already get something assigned? If so, let's skip to the next */
+ if (width[j] != (size_t) -1)
+ continue;
+
+ if (weight_sum == 0)
+ w = minimum_width[j] + extra / (display_columns - j); /* avoid division by zero */
+ else
+ w = minimum_width[j] + (extra * column_weight[j]) / weight_sum;
+
+ if (w >= requested_width[j]) {
+ /* Never give more than requested. If we hit a column like this, there's more
+ * space to allocate to other columns which means we need to restart the
+ * iteration. However, if we hit a column like this, let's assign it the space
+ * it wanted for good early.*/
+
+ w = requested_width[j];
+ restart = true;
+
+ } else if (!finalize)
+ continue;
+
+ width[j] = w;
+
+ assert(w >= minimum_width[j]);
+ delta = w - minimum_width[j];
+
+ assert(delta <= extra);
+ extra -= delta;
+
+ assert(weight_sum >= column_weight[j]);
+ weight_sum -= column_weight[j];
+
+ if (restart)
+ break;
+ }
+
+ if (finalize) {
+ assert(!restart);
+ break;
+ }
+
+ if (!restart)
+ finalize = true;
+ }
+ }
+
+ /* Second pass: show output */
+ for (i = t->header ? 0 : 1; i < n_rows; i++) {
+ TableData **row;
+
+ if (sorted)
+ row = t->data + sorted[i];
+ else
+ row = t->data + i * t->n_columns;
+
+ for (j = 0; j < display_columns; j++) {
+ _cleanup_free_ char *buffer = NULL;
+ const char *field;
+ TableData *d;
+ size_t l;
+
+ assert_se(d = row[t->display_map ? t->display_map[j] : j]);
+
+ field = table_data_format(d);
+ if (!field)
+ return -ENOMEM;
+
+ l = utf8_console_width(field);
+ if (l > width[j]) {
+ /* Field is wider than allocated space. Let's ellipsize */
+
+ buffer = ellipsize(field, width[j], d->ellipsize_percent);
+ if (!buffer)
+ return -ENOMEM;
+
+ field = buffer;
+
+ } else if (l < width[j]) {
+ /* Field is shorter than allocated space. Let's align with spaces */
+
+ buffer = align_string_mem(field, width[j], d->align_percent);
+ if (!buffer)
+ return -ENOMEM;
+
+ field = buffer;
+ }
+
+ if (j > 0)
+ fputc(' ', f); /* column separator */
+
+ if (d->color)
+ fputs(d->color, f);
+
+ fputs(field, f);
+
+ if (d->color)
+ fputs(ansi_normal(), f);
+ }
+
+ fputc('\n', f);
+ }
+
+ return fflush_and_check(f);
+}
+
+int table_format(Table *t, char **ret) {
+ _cleanup_fclose_ FILE *f = NULL;
+ char *buf = NULL;
+ size_t sz = 0;
+ int r;
+
+ f = open_memstream(&buf, &sz);
+ if (!f)
+ return -ENOMEM;
+
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
+ r = table_print(t, f);
+ if (r < 0)
+ return r;
+
+ f = safe_fclose(f);
+
+ *ret = buf;
+
+ return 0;
+}
+
+size_t table_get_rows(Table *t) {
+ if (!t)
+ return 0;
+
+ assert(t->n_columns > 0);
+ return t->n_cells / t->n_columns;
+}
+
+size_t table_get_columns(Table *t) {
+ if (!t)
+ return 0;
+
+ assert(t->n_columns > 0);
+ return t->n_columns;
+}
diff --git a/src/basic/format-table.h b/src/basic/format-table.h
new file mode 100644
index 0000000000..6dc2d16052
--- /dev/null
+++ b/src/basic/format-table.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "macro.h"
+
+typedef enum TableDataType {
+ TABLE_EMPTY,
+ TABLE_STRING,
+ TABLE_BOOLEAN,
+ TABLE_TIMESTAMP,
+ TABLE_TIMESPAN,
+ TABLE_SIZE,
+ TABLE_UINT32,
+ _TABLE_DATA_TYPE_MAX,
+ _TABLE_DATA_TYPE_INVALID = -1,
+} TableDataType;
+
+typedef struct Table Table;
+typedef struct TableCell TableCell;
+
+Table *table_new_internal(const char *first_header, ...) _sentinel_;
+#define table_new(...) table_new_internal(__VA_ARGS__, NULL)
+Table *table_new_raw(size_t n_columns);
+Table *table_unref(Table *t);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Table*, table_unref);
+
+int table_add_cell_full(Table *t, TableCell **ret_cell, TableDataType type, const void *data, size_t minimum_width, size_t maximum_width, unsigned weight, unsigned align_percent, unsigned ellipsize_percent);
+static inline int table_add_cell(Table *t, TableCell **ret_cell, TableDataType type, const void *data) {
+ return table_add_cell_full(t, ret_cell, type, data, (size_t) -1, (size_t) -1, (unsigned) -1, (unsigned) -1, (unsigned) -1);
+}
+
+int table_dup_cell(Table *t, TableCell *cell);
+
+int table_set_minimum_width(Table *t, TableCell *cell, size_t minimum_width);
+int table_set_maximum_width(Table *t, TableCell *cell, size_t maximum_width);
+int table_set_weight(Table *t, TableCell *cell, unsigned weight);
+int table_set_align_percent(Table *t, TableCell *cell, unsigned percent);
+int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent);
+int table_set_color(Table *t, TableCell *cell, const char *color);
+
+int table_add_many_internal(Table *t, TableDataType first_type, ...);
+#define table_add_many(t, ...) table_add_many_internal(t, __VA_ARGS__, _TABLE_DATA_TYPE_MAX)
+
+void table_set_header(Table *table, bool b);
+void table_set_width(Table *t, size_t width);
+int table_set_display(Table *t, size_t first_column, ...);
+int table_set_sort(Table *t, size_t first_column, ...);
+
+int table_print(Table *t, FILE *f);
+int table_format(Table *t, char **ret);
+
+static inline TableCell* TABLE_HEADER_CELL(size_t i) {
+ return SIZE_TO_PTR(i + 1);
+}
+
+size_t table_get_rows(Table *t);
+size_t table_get_columns(Table *t);
diff --git a/src/basic/format-util.h b/src/basic/format-util.h
index d9a78f7811..160550cd68 100644
--- a/src/basic/format-util.h
+++ b/src/basic/format-util.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <inttypes.h>
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index c65ba4bfe5..3a8b32d881 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stddef.h>
@@ -243,6 +225,22 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
return 0;
}
+int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
+ /* Under the assumption that we are running privileged we
+ * first change the access mode and only then hand out
+ * ownership to avoid a window where access is too open. */
+
+ if (mode != MODE_INVALID)
+ if (fchmod(fd, mode) < 0)
+ return -errno;
+
+ if (uid != UID_INVALID || gid != GID_INVALID)
+ if (fchown(fd, uid, gid) < 0)
+ return -errno;
+
+ return 0;
+}
+
int fchmod_umask(int fd, mode_t m) {
mode_t u;
int r;
@@ -254,6 +252,21 @@ int fchmod_umask(int fd, mode_t m) {
return r;
}
+int fchmod_opath(int fd, mode_t m) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+ /* This function operates also on fd that might have been opened with
+ * O_PATH. Indeed fchmodat() doesn't have the AT_EMPTY_PATH flag like
+ * fchownat() does. */
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+
+ if (chmod(procfs_path, m) < 0)
+ return -errno;
+
+ return 0;
+}
+
int fd_warn_permissions(const char *path, int fd) {
struct stat st;
@@ -458,10 +471,8 @@ int get_files_in_directory(const char *path, char ***list) {
n++;
}
- if (list) {
- *list = l;
- l = NULL; /* avoid freeing */
- }
+ if (list)
+ *list = TAKE_PTR(l);
return n;
}
@@ -593,7 +604,7 @@ static bool safe_transition(const struct stat *a, const struct stat *b) {
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
_cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
_cleanup_close_ int fd = -1;
- unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
+ unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */
struct stat previous_stat;
bool exists = true;
char *todo;
@@ -602,7 +613,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
assert(path);
/* Either the file may be missing, or we return an fd to the final object, but both make no sense */
- if ((flags & (CHASE_NONEXISTENT|CHASE_OPEN)) == (CHASE_NONEXISTENT|CHASE_OPEN))
+ if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN))
+ return -EINVAL;
+
+ if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN))
return -EINVAL;
if (isempty(path))
@@ -626,12 +640,43 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
* as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
* function what to do when encountering a symlink with an absolute path as directory: prefix it by the
- * specified path. */
+ * specified path.
+ *
+ * There are three ways to invoke this function:
+ *
+ * 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned
+ * in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set 0 is returned if the file
+ * doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set >= 0 is returned if the destination was
+ * found, -ENOENT if it doesn't.
+ *
+ * 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file
+ * descriptor is returned as return value. This is useful to open files relative to some root
+ * directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using
+ * fd_reopen() or such) before it can be used for reading/writing. CHASE_OPEN may not be combined with
+ * CHASE_NONEXISTENT.
+ *
+ * 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first
+ * symlink or ".." component of the path is resolved, and the resulting path is returned. This is useful if
+ * a caller wants to trace the a path through the file system verbosely. Returns < 0 on error, > 0 if the
+ * path is fully normalized, and == 0 for each normalization step. This may be combined with
+ * CHASE_NONEXISTENT, in which case 1 is returned when a component is not found.
+ *
+ * */
/* A root directory of "/" or "" is identical to none */
- if (isempty(original_root) || path_equal(original_root, "/"))
+ if (empty_or_root(original_root))
original_root = NULL;
+ if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) {
+ /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
+ * and doesn't care about any of the other special features we provide either. */
+ r = open(path, O_PATH|O_CLOEXEC);
+ if (r < 0)
+ return -errno;
+
+ return r;
+ }
+
if (original_root) {
r = path_make_absolute_cwd(original_root, &root);
if (r < 0)
@@ -685,8 +730,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
/* Just a single slash? Then we reached the end. */
if (path_equal(first, "/")) {
/* Preserve the trailing slash */
- if (!strextend(&done, "/", NULL))
- return -ENOMEM;
+
+ if (flags & CHASE_TRAIL_SLASH)
+ if (!strextend(&done, "/", NULL))
+ return -ENOMEM;
break;
}
@@ -702,7 +749,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
/* If we already are at the top, then going up will not change anything. This is in-line with
* how the kernel handles this. */
- if (isempty(done) || path_equal(done, "/"))
+ if (empty_or_root(done))
continue;
parent = dirname_malloc(done);
@@ -717,6 +764,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
free_and_replace(done, parent);
+ if (flags & CHASE_STEP)
+ goto chased_one;
+
fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
if (fd_parent < 0)
return -errno;
@@ -732,8 +782,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
}
safe_close(fd);
- fd = fd_parent;
- fd_parent = -1;
+ fd = TAKE_FD(fd_parent);
continue;
}
@@ -834,14 +883,16 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
free(buffer);
todo = buffer = joined;
+ if (flags & CHASE_STEP)
+ goto chased_one;
+
continue;
}
/* If this is not a symlink, then let's just add the name we read to what we already verified. */
- if (!done) {
- done = first;
- first = NULL;
- } else {
+ if (!done)
+ done = TAKE_PTR(first);
+ else {
/* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
if (streq(done, "/"))
*done = '\0';
@@ -852,8 +903,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
/* And iterate again, but go one directory further down. */
safe_close(fd);
- fd = child;
- child = -1;
+ fd = TAKE_FD(child);
}
if (!done) {
@@ -863,25 +913,154 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return -ENOMEM;
}
- if (ret) {
- *ret = done;
- done = NULL;
- }
+ if (ret)
+ *ret = TAKE_PTR(done);
if (flags & CHASE_OPEN) {
- int q;
-
/* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by
* opening /proc/self/fd/xyz. */
assert(fd >= 0);
- q = fd;
- fd = -1;
-
- return q;
+ return TAKE_FD(fd);
}
+ if (flags & CHASE_STEP)
+ return 1;
+
return exists;
+
+chased_one:
+ if (ret) {
+ char *c;
+
+ c = strjoin(strempty(done), todo);
+ if (!c)
+ return -ENOMEM;
+
+ *ret = c;
+ }
+
+ return 0;
+}
+
+int chase_symlinks_and_open(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ int open_flags,
+ char **ret_path) {
+
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ if (chase_flags & CHASE_NONEXISTENT)
+ return -EINVAL;
+
+ if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ /* Shortcut this call if none of the special features of this call are requested */
+ r = open(path, open_flags);
+ if (r < 0)
+ return -errno;
+
+ return r;
+ }
+
+ path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
+ if (path_fd < 0)
+ return path_fd;
+
+ r = fd_reopen(path_fd, open_flags);
+ if (r < 0)
+ return r;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ return r;
+}
+
+int chase_symlinks_and_opendir(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ char **ret_path,
+ DIR **ret_dir) {
+
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+ DIR *d;
+
+ if (!ret_dir)
+ return -EINVAL;
+ if (chase_flags & CHASE_NONEXISTENT)
+ return -EINVAL;
+
+ if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ /* Shortcut this call if none of the special features of this call are requested */
+ d = opendir(path);
+ if (!d)
+ return -errno;
+
+ *ret_dir = d;
+ return 0;
+ }
+
+ path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
+ if (path_fd < 0)
+ return path_fd;
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", path_fd);
+ d = opendir(procfs_path);
+ if (!d)
+ return -errno;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ *ret_dir = d;
+ return 0;
+}
+
+int chase_symlinks_and_stat(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ char **ret_path,
+ struct stat *ret_stat) {
+
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+
+ assert(path);
+ assert(ret_stat);
+
+ if (chase_flags & CHASE_NONEXISTENT)
+ return -EINVAL;
+
+ if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ /* Shortcut this call if none of the special features of this call are requested */
+ if (stat(path, ret_stat) < 0)
+ return -errno;
+
+ return 1;
+ }
+
+ path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
+ if (path_fd < 0)
+ return path_fd;
+
+ if (fstat(path_fd, ret_stat) < 0)
+ return -errno;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ if (chase_flags & CHASE_OPEN)
+ return TAKE_FD(path_fd);
+
+ return 1;
}
int access_fd(int fd, int mode) {
@@ -891,14 +1070,22 @@ int access_fd(int fd, int mode) {
/* Like access() but operates on an already open fd */
xsprintf(p, "/proc/self/fd/%i", fd);
-
r = access(p, mode);
if (r < 0)
- r = -errno;
+ return -errno;
return r;
}
+void unlink_tempfilep(char (*p)[]) {
+ /* If the file is created with mkstemp(), it will (almost always)
+ * change the suffix. Treat this as a sign that the file was
+ * successfully created. We ignore both the rare case where the
+ * original suffix is used and unlink failures. */
+ if (!endswith(*p, ".XXXXXX"))
+ (void) unlink_noerrno(*p);
+}
+
int unlinkat_deallocate(int fd, const char *name, int flags) {
_cleanup_close_ int truncate_fd = -1;
struct stat st;
@@ -979,9 +1166,9 @@ int fsync_directory_of_file(int fd) {
r = fd_get_path(fd, &path);
if (r < 0) {
- log_debug("Failed to query /proc/self/fd/%d%s: %m",
- fd,
- r == -EOPNOTSUPP ? ", ignoring" : "");
+ log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m",
+ fd,
+ r == -EOPNOTSUPP ? ", ignoring" : "");
if (r == -EOPNOTSUPP)
/* If /proc is not available, we're most likely running in some
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index 82d7e765b3..28566773c6 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -1,25 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
+#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
@@ -43,8 +25,10 @@ int readlink_value(const char *p, char **ret);
int readlink_and_make_absolute(const char *p, char **r);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid);
int fchmod_umask(int fd, mode_t mode);
+int fchmod_opath(int fd, mode_t m);
int fd_warn_permissions(const char *path, int fd);
@@ -81,15 +65,24 @@ union inotify_event_buffer {
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
enum {
- CHASE_PREFIX_ROOT = 1U << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */
- CHASE_NONEXISTENT = 1U << 1, /* If set, it's OK if the path doesn't actually exist. */
- CHASE_NO_AUTOFS = 1U << 2, /* If set, return -EREMOTE if autofs mount point found */
- CHASE_SAFE = 1U << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
- CHASE_OPEN = 1U << 4, /* If set, return an O_PATH object to the final component */
+ CHASE_PREFIX_ROOT = 1 << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */
+ CHASE_NONEXISTENT = 1 << 1, /* If set, it's OK if the path doesn't actually exist. */
+ CHASE_NO_AUTOFS = 1 << 2, /* If set, return -EREMOTE if autofs mount point found */
+ CHASE_SAFE = 1 << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
+ CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */
+ CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */
+ CHASE_STEP = 1 << 6, /* If set, just execute a single step of the normalization */
};
+/* How many iterations to execute before returning -ELOOP */
+#define CHASE_SYMLINKS_MAX 32
+
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
+int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path);
+int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir);
+int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat);
+
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
static inline void rmdir_and_free(char *p) {
PROTECT_ERRNO;
@@ -106,6 +99,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free);
int access_fd(int fd, int mode);
+void unlink_tempfilep(char (*p)[]);
int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd);
diff --git a/src/basic/gcrypt-util.c b/src/basic/gcrypt-util.c
index 34d0d399b7..f304a2bab6 100644
--- a/src/basic/gcrypt-util.c
+++ b/src/basic/gcrypt-util.c
@@ -1,24 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#if HAVE_GCRYPT
#include <gcrypt.h>
diff --git a/src/basic/gcrypt-util.h b/src/basic/gcrypt-util.h
index 714cae673b..87eb606891 100644
--- a/src/basic/gcrypt-util.h
+++ b/src/basic/gcrypt-util.h
@@ -1,24 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#pragma once
diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c
index 4ac56c91d0..9fac676f2b 100644
--- a/src/basic/glob-util.c
+++ b/src/basic/glob-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h
index 911e6d2c1a..8e226c1ee2 100644
--- a/src/basic/glob-util.h
+++ b/src/basic/glob-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <glob.h>
#include <stdbool.h>
#include <string.h>
diff --git a/src/basic/gunicode.c b/src/basic/gunicode.c
index 8aff4a0fc5..c51b1a7a18 100644
--- a/src/basic/gunicode.c
+++ b/src/basic/gunicode.c
@@ -1,7 +1,7 @@
/* gunicode.c - Unicode manipulation functions
*
* Copyright (C) 1999, 2000 Tom Tromey
- * Copyright 2000, 2005 Red Hat, Inc.
+ * Copyright © 2000, 2005 Red Hat, Inc.
*/
#include "gunicode.h"
diff --git a/src/basic/gunicode.h b/src/basic/gunicode.h
index 5975bc8fc9..a16b7b6ff1 100644
--- a/src/basic/gunicode.h
+++ b/src/basic/gunicode.h
@@ -3,7 +3,7 @@
/* gunicode.h - Unicode manipulation functions
*
* Copyright (C) 1999, 2000 Tom Tromey
- * Copyright 2000, 2005 Red Hat, Inc.
+ * Copyright © 2000, 2005 Red Hat, Inc.
*/
#include <stdbool.h>
diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c
index 947bcfd584..db48437be7 100644
--- a/src/basic/hash-funcs.c
+++ b/src/basic/hash-funcs.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
@@ -37,7 +18,6 @@ const struct hash_ops string_hash_ops = {
.compare = string_compare_func
};
-
void path_hash_func(const void *p, struct siphash *state) {
const char *q = p;
size_t n;
diff --git a/src/basic/hash-funcs.h b/src/basic/hash-funcs.h
index 945b4c251c..5e5989f021 100644
--- a/src/basic/hash-funcs.h
+++ b/src/basic/hash-funcs.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "macro.h"
#include "siphash24.h"
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index d0873f7ae5..69a7d70b04 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdint.h>
@@ -294,7 +275,7 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
},
};
-#ifdef VALGRIND
+#if VALGRIND
__attribute__((destructor)) static void cleanup_pools(void) {
_cleanup_free_ char *t = NULL;
int r;
diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h
index b674910397..5c70c102d7 100644
--- a/src/basic/hashmap.h
+++ b/src/basic/hashmap.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <limits.h>
#include <stdbool.h>
diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c
index fe7e4954ef..7748e8352c 100644
--- a/src/basic/hexdecoct.c
+++ b/src/basic/hexdecoct.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <ctype.h>
#include <errno.h>
@@ -90,33 +72,69 @@ char *hexmem(const void *p, size_t l) {
return r;
}
-int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
- _cleanup_free_ uint8_t *r = NULL;
- uint8_t *z;
+static int unhex_next(const char **p, size_t *l) {
+ int r;
+
+ assert(p);
+ assert(l);
+
+ /* Find the next non-whitespace character, and decode it. We
+ * greedily skip all preceeding and all following whitespace. */
+
+ for (;;) {
+ if (*l == 0)
+ return -EPIPE;
+
+ if (!strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip leading whitespace */
+ (*p)++, (*l)--;
+ }
+
+ r = unhexchar(**p);
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ (*p)++, (*l)--;
+
+ if (*l == 0 || !strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip following whitespace */
+ }
+
+ return r;
+}
+
+int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
+ _cleanup_free_ uint8_t *buf = NULL;
const char *x;
+ uint8_t *z;
- assert(mem);
- assert(len);
+ assert(ret);
+ assert(ret_len);
assert(p || l == 0);
if (l == (size_t) -1)
l = strlen(p);
- if (l % 2 != 0)
- return -EINVAL;
-
- z = r = malloc((l + 1) / 2 + 1);
- if (!r)
+ /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
+ buf = malloc((l + 1) / 2 + 1);
+ if (!buf)
return -ENOMEM;
- for (x = p; x < p + l; x += 2) {
+ for (x = p, z = buf;;) {
int a, b;
- a = unhexchar(x[0]);
+ a = unhex_next(&x, &l);
+ if (a == -EPIPE) /* End of string */
+ break;
if (a < 0)
return a;
- b = unhexchar(x[1]);
+ b = unhex_next(&x, &l);
if (b < 0)
return b;
@@ -125,9 +143,8 @@ int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
*z = 0;
- *mem = r;
- r = NULL;
- *len = (l + 1) / 2;
+ *ret_len = (size_t) (z - buf);
+ *ret = TAKE_PTR(buf);
return 0;
}
@@ -195,7 +212,7 @@ char *base32hexmem(const void *p, size_t l, bool padding) {
for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
- x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
+ * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
*(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
*(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
*(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
@@ -295,7 +312,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
}
/* a group of eight input bytes needs five output bytes, in case of
- padding we need to add some extra bytes */
+ * padding we need to add some extra bytes */
len = (l / 8) * 5;
switch (l % 8) {
@@ -323,7 +340,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
for (x = p; x < p + (l / 8) * 8; x += 8) {
/* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
- e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
+ * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
a = unbase32hexchar(x[0]);
if (a < 0)
return -EINVAL;
@@ -482,8 +499,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
*z = 0;
- *mem = r;
- r = NULL;
+ *mem = TAKE_PTR(r);
*_len = len;
return 0;
@@ -583,7 +599,7 @@ static int base64_append_width(
if (len <= 0)
return len;
- lines = (len + width - 1) / width;
+ lines = DIV_ROUND_UP(len, width);
slen = strlen_ptr(sep);
t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
@@ -680,7 +696,7 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
l = strlen(p);
/* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
- bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
+ * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
buf = malloc(len + 1);
@@ -748,11 +764,8 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
*z = 0;
- if (ret_size)
- *ret_size = (size_t) (z - buf);
-
- *ret = buf;
- buf = NULL;
+ *ret_size = (size_t) (z - buf);
+ *ret = TAKE_PTR(buf);
return 0;
}
diff --git a/src/basic/hexdecoct.h b/src/basic/hexdecoct.h
index 08d0a52276..9477d16e37 100644
--- a/src/basic/hexdecoct.h
+++ b/src/basic/hexdecoct.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index b59e5425a5..09fabe077b 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <limits.h>
diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h
index edae52e3db..749481723d 100644
--- a/src/basic/hostname-util.h
+++ b/src/basic/hostname-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdio.h>
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c
index 572e172b33..aed7601d50 100644
--- a/src/basic/in-addr-util.c
+++ b/src/basic/in-addr-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <endian.h>
diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h
index acaae6d287..956c00a850 100644
--- a/src/basic/in-addr-util.h
+++ b/src/basic/in-addr-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <netinet/in.h>
#include <stddef.h>
#include <sys/socket.h>
diff --git a/src/basic/io-util.c b/src/basic/io-util.c
index a6e34cb762..1f64cc933b 100644
--- a/src/basic/io-util.c
+++ b/src/basic/io-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <limits.h>
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
index d81610ad21..ed189b5820 100644
--- a/src/basic/io-util.h
+++ b/src/basic/io-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -41,9 +22,8 @@ int fd_wait_for_event(int fd, int event, usec_t timeout);
ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
-static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
- unsigned j;
- size_t r = 0;
+static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, size_t n) {
+ size_t j, r = 0;
for (j = 0; j < n; j++)
r += i[j].iov_len;
@@ -51,8 +31,8 @@ static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
return r;
}
-static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
- unsigned j;
+static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
+ size_t j;
for (j = 0; j < n; j++) {
size_t sub;
diff --git a/src/basic/ioprio.h b/src/basic/ioprio.h
index d8bb6eb497..3fb168dafe 100644
--- a/src/basic/ioprio.h
+++ b/src/basic/ioprio.h
@@ -10,8 +10,9 @@
/*
* Gives us 8 prio classes with 13-bits of data for each class
*/
-#define IOPRIO_BITS (16)
-#define IOPRIO_CLASS_SHIFT (13)
+#define IOPRIO_BITS 16
+#define IOPRIO_N_CLASSES 8
+#define IOPRIO_CLASS_SHIFT 13
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
diff --git a/src/basic/journal-importer.c b/src/basic/journal-importer.c
index 11054589e3..ca203bbbfc 100644
--- a/src/basic/journal-importer.c
+++ b/src/basic/journal-importer.c
@@ -1,30 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <unistd.h>
#include "alloc-util.h"
+#include "escape.h"
#include "fd-util.h"
#include "io-util.h"
+#include "journal-file.h"
#include "journal-importer.h"
+#include "journal-util.h"
#include "parse-util.h"
#include "string-util.h"
#include "unaligned.h"
@@ -245,56 +230,78 @@ static int get_data_newline(JournalImporter *imp) {
assert(data);
if (*data != '\n') {
- log_error("expected newline, got '%c'", *data);
+ char buf[4];
+ int l;
+
+ l = cescape_char(*data, buf);
+ log_error("Expected newline, got '%.*s'", l, buf);
return -EINVAL;
}
return 1;
}
-static int process_dunder(JournalImporter *imp, char *line, size_t n) {
- const char *timestamp;
+static int process_special_field(JournalImporter *imp, char *line) {
+ const char *value;
+ char buf[CELLESCAPE_DEFAULT_LENGTH];
int r;
assert(line);
- assert(n > 0);
- assert(line[n-1] == '\n');
-
- /* XXX: is it worth to support timestamps in extended format?
- * We don't produce them, but who knows... */
- timestamp = startswith(line, "__CURSOR=");
- if (timestamp)
+ value = startswith(line, "__CURSOR=");
+ if (value)
/* ignore __CURSOR */
return 1;
- timestamp = startswith(line, "__REALTIME_TIMESTAMP=");
- if (timestamp) {
- long long unsigned x;
- line[n-1] = '\0';
- r = safe_atollu(timestamp, &x);
+ value = startswith(line, "__REALTIME_TIMESTAMP=");
+ if (value) {
+ uint64_t x;
+
+ r = safe_atou64(value, &x);
if (r < 0)
- log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp);
- else
- imp->ts.realtime = x;
- return r < 0 ? r : 1;
+ return log_warning_errno(r, "Failed to parse __REALTIME_TIMESTAMP '%s': %m",
+ cellescape(buf, sizeof buf, value));
+ else if (!VALID_REALTIME(x)) {
+ log_warning("__REALTIME_TIMESTAMP out of range, ignoring: %"PRIu64, x);
+ return -ERANGE;
+ }
+
+ imp->ts.realtime = x;
+ return 1;
}
- timestamp = startswith(line, "__MONOTONIC_TIMESTAMP=");
- if (timestamp) {
- long long unsigned x;
- line[n-1] = '\0';
- r = safe_atollu(timestamp, &x);
+ value = startswith(line, "__MONOTONIC_TIMESTAMP=");
+ if (value) {
+ uint64_t x;
+
+ r = safe_atou64(value, &x);
if (r < 0)
- log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp);
- else
- imp->ts.monotonic = x;
- return r < 0 ? r : 1;
+ return log_warning_errno(r, "Failed to parse __MONOTONIC_TIMESTAMP '%s': %m",
+ cellescape(buf, sizeof buf, value));
+ else if (!VALID_MONOTONIC(x)) {
+ log_warning("__MONOTONIC_TIMESTAMP out of range, ignoring: %"PRIu64, x);
+ return -ERANGE;
+ }
+
+ imp->ts.monotonic = x;
+ return 1;
+ }
+
+ /* Just a single underline, but it needs special treatment too. */
+ value = startswith(line, "_BOOT_ID=");
+ if (value) {
+ r = sd_id128_from_string(value, &imp->boot_id);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to parse _BOOT_ID '%s': %m",
+ cellescape(buf, sizeof buf, value));
+
+ /* store the field in the usual fashion too */
+ return 0;
}
- timestamp = startswith(line, "__");
- if (timestamp) {
- log_notice("Unknown dunder line %s", line);
+ value = startswith(line, "__");
+ if (value) {
+ log_notice("Unknown dunder line __%s, ignoring.", cellescape(buf, sizeof buf, value));
return 1;
}
@@ -327,10 +334,6 @@ int journal_importer_process_data(JournalImporter *imp) {
return 1;
}
- r = process_dunder(imp, line, n);
- if (r != 0)
- return r < 0 ? r : 0;
-
/* MESSAGE=xxx\n
or
COREDUMP\n
@@ -341,6 +344,21 @@ int journal_importer_process_data(JournalImporter *imp) {
/* chomp newline */
n--;
+ if (!journal_field_valid(line, sep - line, true)) {
+ char buf[64], *t;
+
+ t = strndupa(line, sep - line);
+ log_debug("Ignoring invalid field: \"%s\"",
+ cellescape(buf, sizeof buf, t));
+
+ return 0;
+ }
+
+ line[n] = '\0';
+ r = process_special_field(imp, line);
+ if (r != 0)
+ return r < 0 ? r : 0;
+
r = iovw_put(&imp->iovw, line, n);
if (r < 0)
return r;
diff --git a/src/basic/journal-importer.h b/src/basic/journal-importer.h
index d11caa2396..f49ce734a1 100644
--- a/src/basic/journal-importer.h
+++ b/src/basic/journal-importer.h
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#pragma once
@@ -24,6 +6,8 @@
#include <stdbool.h>
#include <sys/uio.h>
+#include "sd-id128.h"
+
#include "time-util.h"
/* Make sure not to make this smaller than the maximum coredump size.
@@ -58,6 +42,7 @@ typedef struct JournalImporter {
int state;
dual_timestamp ts;
+ sd_id128_t boot_id;
} JournalImporter;
void journal_importer_cleanup(JournalImporter *);
diff --git a/src/basic/khash.c b/src/basic/khash.c
index 6463faf3e1..847f2572a6 100644
--- a/src/basic/khash.c
+++ b/src/basic/khash.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/if_alg.h>
#include <stdbool.h>
@@ -216,8 +198,7 @@ int khash_dup(khash *h, khash **ret) {
if (copy->fd < 0)
return -errno;
- *ret = copy;
- copy = NULL;
+ *ret = TAKE_PTR(copy);
return 0;
}
diff --git a/src/basic/khash.h b/src/basic/khash.h
index e9c41a3f20..a3013b9d61 100644
--- a/src/basic/khash.h
+++ b/src/basic/khash.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <sys/types.h>
#include <sys/uio.h>
diff --git a/src/basic/label.c b/src/basic/label.c
index 18c9a23fea..12a7fb0945 100644
--- a/src/basic/label.c
+++ b/src/basic/label.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <sys/stat.h>
@@ -28,11 +10,11 @@
#include "selinux-util.h"
#include "smack-util.h"
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int label_fix(const char *path, LabelFixFlags flags) {
int r, q;
- r = mac_selinux_fix(path, ignore_enoent, ignore_erofs);
- q = mac_smack_fix(path, ignore_enoent, ignore_erofs);
+ r = mac_selinux_fix(path, flags);
+ q = mac_smack_fix(path, flags);
if (r < 0)
return r;
@@ -60,7 +42,7 @@ int symlink_label(const char *old_path, const char *new_path) {
if (r < 0)
return r;
- return mac_smack_fix(new_path, false, false);
+ return mac_smack_fix(new_path, 0);
}
int btrfs_subvol_make_label(const char *path) {
@@ -78,5 +60,5 @@ int btrfs_subvol_make_label(const char *path) {
if (r < 0)
return r;
- return mac_smack_fix(path, false, false);
+ return mac_smack_fix(path, 0);
}
diff --git a/src/basic/label.h b/src/basic/label.h
index d73dacec4f..08fd109bcf 100644
--- a/src/basic/label.h
+++ b/src/basic/label.h
@@ -1,29 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+typedef enum LabelFixFlags {
+ LABEL_IGNORE_ENOENT = 1 << 0,
+ LABEL_IGNORE_EROFS = 1 << 1,
+} LabelFixFlags;
+
+int label_fix(const char *path, LabelFixFlags flags);
int mkdir_label(const char *path, mode_t mode);
int symlink_label(const char *old_path, const char *new_path);
diff --git a/src/basic/list.h b/src/basic/list.h
index 7006c3e273..643e0bea88 100644
--- a/src/basic/list.h
+++ b/src/basic/list.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
/* The head of the linked list. Use this in the structure that shall
* contain the head of the linked list */
#define LIST_HEAD(t,name) \
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index 266cb29936..3ad352f22f 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -84,7 +66,7 @@ static int add_locales_from_archive(Set *locales) {
_cleanup_close_ int fd = -1;
size_t sz = 0;
struct stat st;
- unsigned i;
+ size_t i;
int r;
fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
@@ -196,8 +178,7 @@ int get_locales(char ***ret) {
strv_sort(l);
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
return 0;
}
@@ -320,7 +301,7 @@ int get_keymaps(char ***ret) {
return -ENOMEM;
NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
- r = nftw(dir, nftw_cb, 20, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+ r = nftw(dir, nftw_cb, 20, FTW_PHYS|FTW_ACTIONRETVAL);
if (r == FTW_STOP)
log_debug("Directory not found %s", dir);
@@ -341,8 +322,7 @@ int get_keymaps(char ***ret) {
strv_sort(l);
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
return 0;
}
@@ -369,6 +349,13 @@ bool keymap_is_valid(const char *name) {
const char *special_glyph(SpecialGlyph code) {
+ /* A list of a number of interesting unicode glyphs we can use to decorate our output. It's probably wise to be
+ * conservative here, and primarily stick to the glyphs defined in the eurlatgr font, so that display still
+ * works reasonably well on the Linux console. For details see:
+ *
+ * http://git.altlinux.org/people/legion/packages/kbd.git?p=kbd.git;a=blob;f=data/consolefonts/README.eurlatgr
+ */
+
static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = {
/* ASCII fallback */
[false] = {
@@ -380,10 +367,11 @@ const char *special_glyph(SpecialGlyph code) {
[BLACK_CIRCLE] = "*",
[ARROW] = "->",
[MDASH] = "-",
+ [ELLIPSIS] = "..."
},
/* UTF-8 */
- [ true ] = {
+ [true] = {
[TREE_VERTICAL] = "\342\224\202 ", /* │ */
[TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
[TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
@@ -392,6 +380,7 @@ const char *special_glyph(SpecialGlyph code) {
[BLACK_CIRCLE] = "\342\227\217", /* ● */
[ARROW] = "\342\206\222", /* → */
[MDASH] = "\342\200\223", /* – */
+ [ELLIPSIS] = "\342\200\246", /* … */
},
};
diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h
index f75dcbc3d1..775fe8bc72 100644
--- a/src/basic/locale-util.h
+++ b/src/basic/locale-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <libintl.h>
#include <stdbool.h>
#include <locale.h>
@@ -66,6 +47,7 @@ typedef enum {
BLACK_CIRCLE,
ARROW,
MDASH,
+ ELLIPSIS,
_SPECIAL_GLYPH_MAX
} SpecialGlyph;
diff --git a/src/basic/lockfile-util.c b/src/basic/lockfile-util.c
index f4761a9d55..4bae23b243 100644
--- a/src/basic/lockfile-util.c
+++ b/src/basic/lockfile-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/basic/lockfile-util.h b/src/basic/lockfile-util.h
index 1e86ad7442..c2abd9956f 100644
--- a/src/basic/lockfile-util.h
+++ b/src/basic/lockfile-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stddef.h>
#include "macro.h"
@@ -35,6 +16,4 @@ int make_lock_file(const char *p, int operation, LockFile *ret);
int make_lock_file_for(const char *p, int operation, LockFile *ret);
void release_lock_file(LockFile *f);
-#define _cleanup_release_lock_file_ _cleanup_(release_lock_file)
-
#define LOCK_FILE_INIT { .fd = -1, .path = NULL }
diff --git a/src/basic/log.c b/src/basic/log.c
index 9a39da7c16..48c094b548 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -354,8 +336,8 @@ static int write_to_console(
char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
struct iovec iovec[6] = {};
- unsigned n = 0;
bool highlight;
+ size_t n = 0;
if (console_fd < 0)
return 0;
@@ -1050,13 +1032,9 @@ int log_struct_iovec_internal(
return -error;
}
- for (i = 0; i < n_input_iovec; i++) {
- if (input_iovec[i].iov_len < STRLEN("MESSAGE="))
- continue;
-
- if (memcmp(input_iovec[i].iov_base, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
+ for (i = 0; i < n_input_iovec; i++)
+ if (memory_startswith(input_iovec[i].iov_base, input_iovec[i].iov_len, "MESSAGE="))
break;
- }
if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
return -error;
@@ -1343,3 +1321,20 @@ int log_emergency_level(void) {
return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;
}
+
+int log_dup_console(void) {
+ int copy;
+
+ /* Duplicate the fd we use for fd logging if it's < 3 and use the copy from now on. This call is useful
+ * whenever we want to continue logging through the original fd, but want to rearrange stderr. */
+
+ if (console_fd >= 3)
+ return 0;
+
+ copy = fcntl(console_fd, F_DUPFD_CLOEXEC, 3);
+ if (copy < 0)
+ return -errno;
+
+ console_fd = copy;
+ return 0;
+}
diff --git a/src/basic/log.h b/src/basic/log.h
index 314be128a2..e1f5fd30cd 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -258,7 +239,7 @@ int log_emergency_level(void);
/* Structured logging */
#define log_struct_errno(level, error, ...) \
log_struct_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
- error, __FILE__, __LINE__, __func__, __VA_ARGS__)
+ error, __FILE__, __LINE__, __func__, __VA_ARGS__, NULL)
#define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__)
#define log_struct_iovec_errno(level, error, iovec, n_iovec) \
@@ -297,6 +278,8 @@ void log_set_open_when_needed(bool b);
* stderr, the console or kmsg */
void log_set_prohibit_ipc(bool b);
+int log_dup_console(void);
+
int log_syntax_internal(
const char *unit,
int level,
diff --git a/src/basic/login-util.c b/src/basic/login-util.c
index af4539453a..085ccd0915 100644
--- a/src/basic/login-util.c
+++ b/src/basic/login-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
diff --git a/src/basic/login-util.h b/src/basic/login-util.h
index 1c558bfe20..e1e62e12b7 100644
--- a/src/basic/login-util.h
+++ b/src/basic/login-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <unistd.h>
diff --git a/src/basic/macro.h b/src/basic/macro.h
index 3a6fc6f585..d1365f7058 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
@@ -63,6 +44,17 @@
#endif
#endif
+#if !defined(HAS_FEATURE_MEMORY_SANITIZER)
+# if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+# define HAS_FEATURE_MEMORY_SANITIZER 1
+# endif
+# endif
+# if !defined(HAS_FEATURE_MEMORY_SANITIZER)
+# define HAS_FEATURE_MEMORY_SANITIZER 0
+# endif
+#endif
+
/* Temporarily disable some warnings */
#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
_Pragma("GCC diagnostic push"); \
@@ -352,13 +344,15 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
({ \
typeof(x) _x_ = (x); \
unsigned ans = 1; \
- while (_x_ /= 10) \
+ while ((_x_ /= 10) != 0) \
ans++; \
ans; \
})
#define SET_FLAG(v, flag, b) \
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
+#define FLAGS_SET(v, flags) \
+ (((v) & (flags)) == (flags))
#define CASE_F(X) case X:
#define CASE_F_1(CASE, X) CASE_F(X)
@@ -427,7 +421,6 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
static inline void func##p(type *p) { \
if (*p) \
func(*p); \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#include "log.h"
diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c
index e7eb895462..f88f0fc80c 100644
--- a/src/basic/memfd-util.c
+++ b/src/basic/memfd-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -168,8 +150,5 @@ int memfd_new_and_map(const char *name, size_t sz, void **p) {
if (r < 0)
return r;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h
index 1d66c98cce..5ebb519931 100644
--- a/src/basic/memfd-util.h
+++ b/src/basic/memfd-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/src/basic/mempool.c b/src/basic/mempool.c
index 0da8e1f775..a5ec8a1020 100644
--- a/src/basic/mempool.c
+++ b/src/basic/mempool.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-2014 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdint.h>
#include <stdlib.h>
@@ -28,12 +9,12 @@
struct pool {
struct pool *next;
- unsigned n_tiles;
- unsigned n_used;
+ size_t n_tiles;
+ size_t n_used;
};
void* mempool_alloc_tile(struct mempool *mp) {
- unsigned i;
+ size_t i;
/* When a tile is released we add it to the list and simply
* place the next pointer at its offset 0. */
@@ -51,8 +32,7 @@ void* mempool_alloc_tile(struct mempool *mp) {
if (_unlikely_(!mp->first_pool) ||
_unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) {
- unsigned n;
- size_t size;
+ size_t size, n;
struct pool *p;
n = mp->first_pool ? mp->first_pool->n_tiles : 0;
@@ -90,7 +70,7 @@ void mempool_free_tile(struct mempool *mp, void *p) {
mp->freelist = p;
}
-#ifdef VALGRIND
+#if VALGRIND
void mempool_drop(struct mempool *mp) {
struct pool *p = mp->first_pool;
diff --git a/src/basic/mempool.h b/src/basic/mempool.h
index c9235c8361..2a41cb358c 100644
--- a/src/basic/mempool.h
+++ b/src/basic/mempool.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011-2014 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
@@ -42,7 +23,6 @@ static struct mempool pool_name = { \
.at_least = alloc_at_least, \
}
-
-#ifdef VALGRIND
+#if VALGRIND
void mempool_drop(struct mempool *mp);
#endif
diff --git a/src/basic/meson.build b/src/basic/meson.build
index c71599db7b..31625b1785 100644
--- a/src/basic/meson.build
+++ b/src/basic/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
basic_sources = files('''
MurmurHash2.c
@@ -90,6 +75,8 @@ basic_sources = files('''
fileio-label.h
fileio.c
fileio.h
+ format-table.c
+ format-table.h
format-util.h
fs-util.c
fs-util.h
@@ -140,6 +127,10 @@ basic_sources = files('''
nss-util.h
ordered-set.c
ordered-set.h
+ pager.c
+ pager.h
+ os-util.c
+ os-util.h
parse-util.c
parse-util.h
path-util.c
@@ -172,7 +163,6 @@ basic_sources = files('''
securebits.h
selinux-util.c
selinux-util.h
- set.c
set.h
sigbus.c
sigbus.h
@@ -312,6 +302,9 @@ foreach item : [['af', af_list_txt, 'af', ''],
endforeach
basic_sources += [missing_h] + generated_gperf_headers
+basic_gcrypt_sources = files(
+ 'gcrypt-util.c',
+ 'gcrypt-util.h')
libbasic = static_library(
'basic',
@@ -329,8 +322,7 @@ libbasic = static_library(
# unnecessary linking to libgcrypt.
libbasic_gcrypt = static_library(
'basic-gcrypt',
- 'gcrypt-util.c',
- 'gcrypt-util.h',
+ basic_gcrypt_sources,
include_directories : includes,
dependencies : [libgcrypt],
c_args : ['-fvisibility=default'])
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 1cc3f08e48..71a07d0574 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
/* Missing glibc definitions to access certain kernel APIs */
#include <errno.h>
@@ -342,7 +323,6 @@ struct btrfs_ioctl_search_header {
__u32 len;
};
-
struct btrfs_ioctl_search_args {
struct btrfs_ioctl_search_key key;
char buf[BTRFS_SEARCH_ARGS_BUFSIZE];
@@ -1058,6 +1038,10 @@ struct input_mask {
#define RTAX_QUICKACK 15
#endif
+#ifndef RTA_EXPIRES
+#define RTA_EXPIRES 23
+#endif
+
#ifndef IPV6_UNICAST_IF
#define IPV6_UNICAST_IF 76
#endif
@@ -1066,6 +1050,10 @@ struct input_mask {
#define IPV6_MIN_MTU 1280
#endif
+#ifndef IPV4_MIN_MTU
+#define IPV4_MIN_MTU 68
+#endif
+
#ifndef IFF_MULTI_QUEUE
#define IFF_MULTI_QUEUE 0x100
#endif
@@ -1413,4 +1401,11 @@ struct statx {
#define AT_STATX_DONT_SYNC 0x4000
#endif
+/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of the same
+ * name, which we need in userspace at various places but is not defined in userspace currently, neither under this
+ * name nor any other. */
+#ifndef TASK_COMM_LEN
+#define TASK_COMM_LEN 16
+#endif
+
#include "missing_syscall.h"
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index 86422ced72..93c60458bf 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -1,26 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
/* Missing glibc definitions to access certain kernel APIs */
#include <sys/types.h>
@@ -269,7 +249,6 @@ static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long i
# define kcmp missing_kcmp
#endif
-
/* ======================================================================= */
#if !HAVE_KEYCTL
diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c
index 6f3a46f467..1d51e92e9a 100644
--- a/src/basic/mkdir-label.c
+++ b/src/basic/mkdir-label.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 <stdio.h>
#include <sys/stat.h>
@@ -44,11 +25,11 @@ int mkdir_label(const char *path, mode_t mode) {
if (r < 0)
return r;
- return mac_smack_fix(path, false, false);
+ return mac_smack_fix(path, 0);
}
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink) {
- return mkdir_safe_internal(path, mode, uid, gid, follow_symlink, mkdir_label);
+int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
+ return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_label);
}
int mkdir_parents_label(const char *path, mode_t mode) {
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
index de4746c867..6ab1b4422b 100644
--- a/src/basic/mkdir.c
+++ b/src/basic/mkdir.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdbool.h>
@@ -29,9 +11,10 @@
#include "mkdir.h"
#include "path-util.h"
#include "stat-util.h"
+#include "stdio-util.h"
#include "user-util.h"
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink, mkdir_func_t _mkdir) {
+int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) {
struct stat st;
int r;
@@ -46,26 +29,47 @@ int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, boo
if (lstat(path, &st) < 0)
return -errno;
- if (follow_symlink && S_ISLNK(st.st_mode)) {
+ if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) {
_cleanup_free_ char *p = NULL;
r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p);
if (r < 0)
return r;
if (r == 0)
- return mkdir_safe_internal(p, mode, uid, gid, false, _mkdir);
+ return mkdir_safe_internal(p, mode, uid, gid,
+ flags & ~MKDIR_FOLLOW_SYMLINK,
+ _mkdir);
if (lstat(p, &st) < 0)
return -errno;
}
+ if (!S_ISDIR(st.st_mode)) {
+ log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG,
+ "Path \"%s\" already exists and is not a directory, refusing.", path);
+ return -ENOTDIR;
+ }
if ((st.st_mode & 0007) > (mode & 0007) ||
(st.st_mode & 0070) > (mode & 0070) ||
- (st.st_mode & 0700) > (mode & 0700) ||
- (uid != UID_INVALID && st.st_uid != uid) ||
- (gid != GID_INVALID && st.st_gid != gid) ||
- !S_ISDIR(st.st_mode))
+ (st.st_mode & 0700) > (mode & 0700)) {
+ log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG,
+ "Directory \"%s\" already exists, but has mode %04o that is too permissive (%04o was requested), refusing.",
+ path, st.st_mode & 0777, mode);
+ return -EEXIST;
+ }
+ if ((uid != UID_INVALID && st.st_uid != uid) ||
+ (gid != GID_INVALID && st.st_gid != gid)) {
+ char u[DECIMAL_STR_MAX(uid_t)] = "-", g[DECIMAL_STR_MAX(gid_t)] = "-";
+
+ if (uid != UID_INVALID)
+ xsprintf(u, UID_FMT, uid);
+ if (gid != UID_INVALID)
+ xsprintf(g, GID_FMT, gid);
+ log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG,
+ "Directory \"%s\" already exists, but is owned by "UID_FMT":"GID_FMT" (%s:%s was requested), refusing.",
+ path, st.st_uid, st.st_gid, u, g);
return -EEXIST;
+ }
return 0;
}
@@ -76,8 +80,8 @@ int mkdir_errno_wrapper(const char *pathname, mode_t mode) {
return 0;
}
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink) {
- return mkdir_safe_internal(path, mode, uid, gid, follow_symlink, mkdir_errno_wrapper);
+int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
+ return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_errno_wrapper);
}
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
diff --git a/src/basic/mkdir.h b/src/basic/mkdir.h
index d6c2d579a3..8e83fb102b 100644
--- a/src/basic/mkdir.h
+++ b/src/basic/mkdir.h
@@ -1,40 +1,26 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Kay Sievers
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/types.h>
+typedef enum MkdirFlags {
+ MKDIR_FOLLOW_SYMLINK = 1 << 0,
+ MKDIR_WARN_MODE = 1 << 1,
+} MkdirFlags;
+
int mkdir_errno_wrapper(const char *pathname, mode_t mode);
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink);
+int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_parents(const char *path, mode_t mode);
int mkdir_p(const char *path, mode_t mode);
/* mandatory access control(MAC) versions */
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink);
+int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_parents_label(const char *path, mode_t mode);
int mkdir_p_label(const char *path, mode_t mode);
/* internally used */
typedef int (*mkdir_func_t)(const char *pathname, mode_t mode);
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink, mkdir_func_t _mkdir);
+int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir);
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
diff --git a/src/basic/module-util.h b/src/basic/module-util.h
index 07956dbffd..8fa121ed98 100644
--- a/src/basic/module-util.h
+++ b/src/basic/module-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <libkmod.h>
#include "macro.h"
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 8151b3a4e4..ebe41a4c6c 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio_ext.h>
@@ -81,10 +63,8 @@ int name_to_handle_at_loop(
if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) {
- if (ret_handle) {
- *ret_handle = h;
- h = NULL;
- }
+ if (ret_handle)
+ *ret_handle = TAKE_PTR(h);
if (ret_mnt_id)
*ret_mnt_id = mnt_id;
@@ -296,7 +276,7 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
* /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
* look at needs to be /usr, not /. */
if (flags & AT_SYMLINK_FOLLOW) {
- r = chase_symlinks(t, root, 0, &canonical);
+ r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical);
if (r < 0)
return r;
@@ -428,7 +408,7 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
if (!cleaned)
return -ENOMEM;
- path_kill_slashes(cleaned);
+ path_simplify(cleaned, false);
done = set_new(&path_hash_ops);
if (!done)
@@ -715,24 +695,33 @@ int repeat_unmount(const char *path, int flags) {
}
const char* mode_to_inaccessible_node(mode_t mode) {
- /* This function maps a node type to the correspondent inaccessible node type.
- * Character and block inaccessible devices may not be created (because major=0 and minor=0),
- * in such case we map character and block devices to the inaccessible node type socket. */
+ /* This function maps a node type to a corresponding inaccessible file node. These nodes are created during
+ * early boot by PID 1. In some cases we lacked the privs to create the character and block devices (maybe
+ * because we run in an userns environment, or miss CAP_SYS_MKNOD, or run with a devices policy that excludes
+ * device nodes with major and minor of 0), but that's fine, in that case we use an AF_UNIX file node instead,
+ * which is not the same, but close enough for most uses. And most importantly, the kernel allows bind mounts
+ * from socket nodes to any non-directory file nodes, and that's the most important thing that matters. */
+
switch(mode & S_IFMT) {
case S_IFREG:
return "/run/systemd/inaccessible/reg";
+
case S_IFDIR:
return "/run/systemd/inaccessible/dir";
+
case S_IFCHR:
if (access("/run/systemd/inaccessible/chr", F_OK) == 0)
return "/run/systemd/inaccessible/chr";
return "/run/systemd/inaccessible/sock";
+
case S_IFBLK:
if (access("/run/systemd/inaccessible/blk", F_OK) == 0)
return "/run/systemd/inaccessible/blk";
return "/run/systemd/inaccessible/sock";
+
case S_IFIFO:
return "/run/systemd/inaccessible/fifo";
+
case S_IFSOCK:
return "/run/systemd/inaccessible/sock";
}
@@ -871,7 +860,6 @@ const char *mount_propagation_flags_to_string(unsigned long flags) {
return NULL;
}
-
int mount_propagation_flags_from_string(const char *name, unsigned long *ret) {
if (isempty(name))
@@ -951,8 +939,7 @@ int mount_option_mangle(
}
*ret_mount_flags = mount_flags;
- *ret_remaining_options = ret;
- ret = NULL;
+ *ret_remaining_options = TAKE_PTR(ret);
return 0;
}
diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h
index fea3e938a8..3cfea3bb20 100644
--- a/src/basic/mount-util.h
+++ b/src/basic/mount-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <fcntl.h>
#include <mntent.h>
#include <stdbool.h>
diff --git a/src/basic/nss-util.h b/src/basic/nss-util.h
index 4fc676395f..2045175d1c 100644
--- a/src/basic/nss-util.h
+++ b/src/basic/nss-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <grp.h>
#include <netdb.h>
#include <nss.h>
@@ -116,8 +97,7 @@ enum nss_status _nss_##module##_gethostbyname_r( \
NULL, \
NULL); \
return ret; \
-} \
-struct __useless_struct_to_allow_trailing_semicolon__
+}
#define NSS_GETHOSTBYADDR_FALLBACKS(module) \
enum nss_status _nss_##module##_gethostbyaddr_r( \
@@ -133,8 +113,7 @@ enum nss_status _nss_##module##_gethostbyaddr_r( \
buffer, buflen, \
errnop, h_errnop, \
NULL); \
-} \
-struct __useless_struct_to_allow_trailing_semicolon__
+}
#define NSS_GETPW_PROTOTYPES(module) \
enum nss_status _nss_##module##_getpwnam_r( \
diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c
index afcf2dbd1d..ed9ba776a4 100644
--- a/src/basic/ordered-set.c
+++ b/src/basic/ordered-set.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "ordered-set.h"
#include "strv.h"
diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
index c4dbd79249..e7c054d8e4 100644
--- a/src/basic/ordered-set.h
+++ b/src/basic/ordered-set.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "hashmap.h"
typedef struct OrderedSet OrderedSet;
@@ -61,6 +42,14 @@ static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value)
return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL);
}
+static inline void* ordered_set_remove(OrderedSet *s, void *p) {
+ return ordered_hashmap_remove((OrderedHashmap*) s, p);
+}
+
+static inline void* ordered_set_steal_first(OrderedSet *s) {
+ return ordered_hashmap_steal_first((OrderedHashmap*) s);
+}
+
int ordered_set_consume(OrderedSet *s, void *p);
int ordered_set_put_strdup(OrderedSet *s, const char *p);
int ordered_set_put_strdupv(OrderedSet *s, char **l);
diff --git a/src/basic/os-util.c b/src/basic/os-util.c
new file mode 100644
index 0000000000..207594cef8
--- /dev/null
+++ b/src/basic/os-util.c
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "os-util.h"
+#include "strv.h"
+#include "fileio.h"
+#include "string-util.h"
+
+int path_is_os_tree(const char *path) {
+ int r;
+
+ assert(path);
+
+ /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
+ * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
+ * the case where just the os-release file is missing. */
+ if (laccess(path, F_OK) < 0)
+ return -errno;
+
+ /* We use {/etc|/usr/lib}/os-release as flag file if something is an OS */
+ r = open_os_release(path, NULL, NULL);
+ if (r == -ENOENT) /* We got nothing */
+ return 0;
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+int open_os_release(const char *root, char **ret_path, int *ret_fd) {
+ _cleanup_free_ char *q = NULL;
+ const char *p;
+ int k;
+
+ FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") {
+ k = chase_symlinks(p, root, CHASE_PREFIX_ROOT|(ret_fd ? CHASE_OPEN : 0), (ret_path ? &q : NULL));
+ if (k != -ENOENT)
+ break;
+ }
+ if (k < 0)
+ return k;
+
+ if (ret_fd) {
+ int real_fd;
+
+ /* Convert the O_PATH fd into a proper, readable one */
+ real_fd = fd_reopen(k, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ safe_close(k);
+ if (real_fd < 0)
+ return real_fd;
+
+ *ret_fd = real_fd;
+ }
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(q);
+
+ return 0;
+}
+
+int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) {
+ _cleanup_free_ char *p = NULL;
+ _cleanup_close_ int fd = -1;
+ FILE *f;
+ int r;
+
+ if (!ret_file)
+ return open_os_release(root, ret_path, NULL);
+
+ r = open_os_release(root, ret_path ? &p : NULL, &fd);
+ if (r < 0)
+ return r;
+
+ f = fdopen(fd, "re");
+ if (!f)
+ return -errno;
+ fd = -1;
+
+ *ret_file = f;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ return 0;
+}
+
+int parse_os_release(const char *root, ...) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ r = fopen_os_release(root, &p, &f);
+ if (r < 0)
+ return r;
+
+ va_start(ap, root);
+ r = parse_env_filev(f, p, NEWLINE, ap);
+ va_end(ap);
+
+ return r;
+}
+
+int load_os_release_pairs(const char *root, char ***ret) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ r = fopen_os_release(root, &p, &f);
+ if (r < 0)
+ return r;
+
+ return load_env_file_pairs(f, p, NEWLINE, ret);
+}
diff --git a/src/basic/os-util.h b/src/basic/os-util.h
new file mode 100644
index 0000000000..6b9e033941
--- /dev/null
+++ b/src/basic/os-util.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdio.h>
+
+int path_is_os_tree(const char *path);
+
+int open_os_release(const char *root, char **ret_path, int *ret_fd);
+int fopen_os_release(const char *root, char **ret_path, FILE **ret_file);
+
+int parse_os_release(const char *root, ...);
+int load_os_release_pairs(const char *root, char ***ret);
diff --git a/src/shared/pager.c b/src/basic/pager.c
index 681af9c40e..f241261119 100644
--- a/src/shared/pager.c
+++ b/src/basic/pager.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <signal.h>
diff --git a/src/basic/pager.h b/src/basic/pager.h
new file mode 100644
index 0000000000..e0fd34af97
--- /dev/null
+++ b/src/basic/pager.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "macro.h"
+
+int pager_open(bool no_pager, bool jump_to_end);
+void pager_close(void);
+bool pager_have(void) _pure_;
+
+int show_man_page(const char *page, bool null_stdio);
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index fa5b4a353a..6becf85878 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <inttypes.h>
@@ -24,12 +6,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
#include "alloc-util.h"
#include "errno-list.h"
#include "extract-word.h"
#include "locale-util.h"
#include "macro.h"
+#include "missing.h"
#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
@@ -106,6 +90,30 @@ int parse_ifindex(const char *s, int *ret) {
return 0;
}
+int parse_mtu(int family, const char *s, uint32_t *ret) {
+ uint64_t u;
+ size_t m;
+ int r;
+
+ r = parse_size(s, 1024, &u);
+ if (r < 0)
+ return r;
+
+ if (u > UINT32_MAX)
+ return -ERANGE;
+
+ if (family == AF_INET6)
+ m = IPV6_MIN_MTU; /* This is 1280 */
+ else
+ m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
+
+ if (u < m)
+ return -ERANGE;
+
+ *ret = (uint32_t) u;
+ return 0;
+}
+
int parse_size(const char *t, uint64_t base, uint64_t *size) {
/* Soo, sometimes we want to parse IEC binary suffixes, and
@@ -324,8 +332,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) {
return -EINVAL;
*error = e;
- *name = n;
- n = NULL;
+ *name = TAKE_PTR(n);
return 0;
}
@@ -371,12 +378,13 @@ finish:
}
-int safe_atou(const char *s, unsigned *ret_u) {
+int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
char *x = NULL;
unsigned long l;
assert(s);
assert(ret_u);
+ assert(base <= 16);
/* strtoul() is happy to parse negative values, and silently
* converts them to unsigned values without generating an
@@ -389,7 +397,7 @@ int safe_atou(const char *s, unsigned *ret_u) {
s += strspn(s, WHITESPACE);
errno = 0;
- l = strtoul(s, &x, 0);
+ l = strtoul(s, &x, base);
if (errno > 0)
return -errno;
if (!x || x == s || *x != 0)
@@ -487,17 +495,18 @@ int safe_atou8(const char *s, uint8_t *ret) {
return 0;
}
-int safe_atou16(const char *s, uint16_t *ret) {
+int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
char *x = NULL;
unsigned long l;
assert(s);
assert(ret);
+ assert(base <= 16);
s += strspn(s, WHITESPACE);
errno = 0;
- l = strtoul(s, &x, 0);
+ l = strtoul(s, &x, base);
if (errno > 0)
return -errno;
if (!x || x == s || *x != 0)
@@ -531,30 +540,6 @@ int safe_atoi16(const char *s, int16_t *ret) {
return 0;
}
-int safe_atoux16(const char *s, uint16_t *ret) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret);
-
- s += strspn(s, WHITESPACE);
-
- errno = 0;
- l = strtoul(s, &x, 16);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x != 0)
- return -EINVAL;
- if (s[0] == '-')
- return -ERANGE;
- if ((unsigned long) (uint16_t) l != l)
- return -ERANGE;
-
- *ret = (uint16_t) l;
- return 0;
-}
-
int safe_atod(const char *s, double *ret_d) {
_cleanup_(freelocalep) locale_t loc = (locale_t) 0;
char *x = NULL;
@@ -642,6 +627,58 @@ int parse_percent(const char *p) {
return v;
}
+int parse_permille_unbounded(const char *p) {
+ const char *pc, *pm, *dot, *n;
+ int r, q, v;
+
+ pm = endswith(p, "‰");
+ if (pm) {
+ n = strndupa(p, pm - p);
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ } else {
+ pc = endswith(p, "%");
+ if (!pc)
+ return -EINVAL;
+
+ dot = memchr(p, '.', pc - p);
+ if (dot) {
+ if (dot + 2 != pc)
+ return -EINVAL;
+ if (dot[1] < '0' || dot[1] > '9')
+ return -EINVAL;
+ q = dot[1] - '0';
+ n = strndupa(p, dot - p);
+ } else {
+ q = 0;
+ n = strndupa(p, pc - p);
+ }
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ if (v > (INT_MAX - q) / 10)
+ return -ERANGE;
+
+ v = v * 10 + q;
+ }
+
+ if (v < 0)
+ return -ERANGE;
+
+ return v;
+}
+
+int parse_permille(const char *p) {
+ int v;
+
+ v = parse_permille_unbounded(p);
+ if (v > 1000)
+ return -ERANGE;
+
+ return v;
+}
+
int parse_nice(const char *p, int *ret) {
int n, r;
@@ -686,3 +723,20 @@ int parse_dev(const char *s, dev_t *ret) {
*ret = d;
return 0;
}
+
+int parse_oom_score_adjust(const char *s, int *ret) {
+ int r, v;
+
+ assert(s);
+ assert(ret);
+
+ r = safe_atoi(s, &v);
+ if (r < 0)
+ return r;
+
+ if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX)
+ return -ERANGE;
+
+ *ret = v;
+ return 0;
+}
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
index 727422056a..f3267f4cfe 100644
--- a/src/basic/parse-util.h
+++ b/src/basic/parse-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <limits.h>
#include <stddef.h>
@@ -35,6 +16,7 @@ int parse_dev(const char *s, dev_t *ret);
int parse_pid(const char *s, pid_t* ret_pid);
int parse_mode(const char *s, mode_t *ret);
int parse_ifindex(const char *s, int *ret);
+int parse_mtu(int family, const char *s, uint32_t *ret);
int parse_size(const char *t, uint64_t base, uint64_t *size);
int parse_range(const char *t, unsigned *lower, unsigned *upper);
@@ -44,17 +26,29 @@ int parse_syscall_and_errno(const char *in, char **name, int *error);
#define FORMAT_BYTES_MAX 8
char *format_bytes(char *buf, size_t l, uint64_t t);
-int safe_atou(const char *s, unsigned *ret_u);
+int safe_atou_full(const char *s, unsigned base, unsigned *ret_u);
+
+static inline int safe_atou(const char *s, unsigned *ret_u) {
+ return safe_atou_full(s, 0, ret_u);
+}
+
int safe_atoi(const char *s, int *ret_i);
int safe_atollu(const char *s, unsigned long long *ret_u);
int safe_atolli(const char *s, long long int *ret_i);
int safe_atou8(const char *s, uint8_t *ret);
-int safe_atou16(const char *s, uint16_t *ret);
-int safe_atoi16(const char *s, int16_t *ret);
+int safe_atou16_full(const char *s, unsigned base, uint16_t *ret);
+
+static inline int safe_atou16(const char *s, uint16_t *ret) {
+ return safe_atou16_full(s, 0, ret);
+}
+
+static inline int safe_atoux16(const char *s, uint16_t *ret) {
+ return safe_atou16_full(s, 16, ret);
+}
-int safe_atoux16(const char *s, uint16_t *ret);
+int safe_atoi16(const char *s, int16_t *ret);
static inline int safe_atou32(const char *s, uint32_t *ret_u) {
assert_cc(sizeof(uint32_t) == sizeof(unsigned));
@@ -115,6 +109,11 @@ int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
int parse_percent_unbounded(const char *p);
int parse_percent(const char *p);
+int parse_permille_unbounded(const char *p);
+int parse_permille(const char *p);
+
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
+
+int parse_oom_score_adjust(const char *s, int *ret);
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index df94629385..d214c72916 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <limits.h>
@@ -45,6 +27,7 @@
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
+#include "utf8.h"
bool path_is_absolute(const char *p) {
return p[0] == '/';
@@ -140,8 +123,8 @@ int path_make_absolute_cwd(const char *p, char **ret) {
}
int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
- char *r, *p;
- unsigned n_parents;
+ char *f, *t, *r, *p;
+ unsigned n_parents = 0;
assert(from_dir);
assert(to_path);
@@ -149,85 +132,81 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
/* Strips the common part, and adds ".." elements as necessary. */
- if (!path_is_absolute(from_dir))
+ if (!path_is_absolute(from_dir) || !path_is_absolute(to_path))
return -EINVAL;
- if (!path_is_absolute(to_path))
- return -EINVAL;
+ f = strdupa(from_dir);
+ t = strdupa(to_path);
+
+ path_simplify(f, true);
+ path_simplify(t, true);
/* Skip the common part. */
for (;;) {
size_t a, b;
- from_dir += strspn(from_dir, "/");
- to_path += strspn(to_path, "/");
+ f += *f == '/';
+ t += *t == '/';
- if (!*from_dir) {
- if (!*to_path)
+ if (!*f) {
+ if (!*t)
/* from_dir equals to_path. */
r = strdup(".");
else
/* from_dir is a parent directory of to_path. */
- r = strdup(to_path);
+ r = strdup(t);
if (!r)
return -ENOMEM;
- path_kill_slashes(r);
-
*_r = r;
return 0;
}
- if (!*to_path)
+ if (!*t)
break;
- a = strcspn(from_dir, "/");
- b = strcspn(to_path, "/");
+ a = strcspn(f, "/");
+ b = strcspn(t, "/");
- if (a != b)
+ if (a != b || memcmp(f, t, a) != 0)
break;
- if (memcmp(from_dir, to_path, a) != 0)
- break;
-
- from_dir += a;
- to_path += b;
+ f += a;
+ t += b;
}
/* If we're here, then "from_dir" has one or more elements that need to
* be replaced with "..". */
/* Count the number of necessary ".." elements. */
- for (n_parents = 0;;) {
+ for (; *f;) {
size_t w;
- from_dir += strspn(from_dir, "/");
-
- if (!*from_dir)
- break;
-
- w = strcspn(from_dir, "/");
+ w = strcspn(f, "/");
/* If this includes ".." we can't do a simple series of "..", refuse */
- if (w == 2 && from_dir[0] == '.' && from_dir[1] == '.')
+ if (w == 2 && f[0] == '.' && f[1] == '.')
return -EINVAL;
- /* Count number of elements, except if they are "." */
- if (w != 1 || from_dir[0] != '.')
- n_parents++;
+ /* Count number of elements */
+ n_parents++;
- from_dir += w;
+ f += w;
+ f += *f == '/';
}
- r = new(char, n_parents * 3 + strlen(to_path) + 1);
+ r = new(char, n_parents * 3 + strlen(t) + 1);
if (!r)
return -ENOMEM;
for (p = r; n_parents > 0; n_parents--)
p = mempcpy(p, "../", 3);
- strcpy(p, to_path);
- path_kill_slashes(r);
+ if (*t)
+ strcpy(p, t);
+ else
+ /* Remove trailing slash */
+ *(--p) = 0;
*_r = r;
return 0;
@@ -248,7 +227,7 @@ int path_strv_make_absolute_cwd(char **l) {
if (r < 0)
return r;
- path_kill_slashes(t);
+ path_simplify(t, false);
free_and_replace(*s, t);
}
@@ -290,8 +269,7 @@ char **path_strv_resolve(char **l, const char *root) {
r = chase_symlinks(t, root, 0, &u);
if (r == -ENOENT) {
if (root) {
- u = orig;
- orig = NULL;
+ u = TAKE_PTR(orig);
free(t);
} else
u = t;
@@ -349,17 +327,30 @@ char **path_strv_resolve_uniq(char **l, const char *root) {
return strv_uniq(l);
}
-char *path_kill_slashes(char *path) {
+char *path_simplify(char *path, bool kill_dots) {
char *f, *t;
- bool slash = false;
+ bool slash = false, ignore_slash = false, absolute;
+
+ assert(path);
- /* Removes redundant inner and trailing slashes. Modifies the
- * passed string in-place.
+ /* Removes redundant inner and trailing slashes. Also removes unnecessary dots
+ * if kill_dots is true. Modifies the passed string in-place.
*
- * ///foo///bar/ becomes /foo/bar
+ * ///foo//./bar/. becomes /foo/./bar/. (if kill_dots is false)
+ * ///foo//./bar/. becomes /foo/bar (if kill_dots is true)
+ * .//./foo//./bar/. becomes ./foo/bar (if kill_dots is false)
+ * .//./foo//./bar/. becomes foo/bar (if kill_dots is true)
*/
- for (f = path, t = path; *f; f++) {
+ absolute = path_is_absolute(path);
+
+ f = path;
+ if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/')) {
+ ignore_slash = true;
+ f++;
+ }
+
+ for (t = path; *f; f++) {
if (*f == '/') {
slash = true;
@@ -367,17 +358,21 @@ char *path_kill_slashes(char *path) {
}
if (slash) {
+ if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/'))
+ continue;
+
slash = false;
- *(t++) = '/';
+ if (ignore_slash)
+ ignore_slash = false;
+ else
+ *(t++) = '/';
}
*(t++) = *f;
}
- /* Special rule, if we are talking of the root directory, a
- trailing slash is good */
-
- if (t == path && slash)
+ /* Special rule, if we are talking of the root directory, a trailing slash is good */
+ if (absolute && t == path)
*(t++) = '/';
*t = 0;
@@ -544,7 +539,7 @@ int find_binary(const char *name, char **ret) {
/* Found it! */
if (ret) {
- *ret = path_kill_slashes(j);
+ *ret = path_simplify(j, false);
j = NULL;
}
@@ -654,7 +649,7 @@ char *prefix_root(const char *root, const char *path) {
while (path[0] == '/' && path[1] == '/')
path++;
- if (isempty(root) || path_equal(root, "/"))
+ if (empty_or_root(root))
return strdup(path);
l = strlen(root) + 1 + strlen(path) + 1;
@@ -698,12 +693,12 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
if (r < 0)
return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
- path_kill_slashes(p);
- if (suppress_root && path_equal(p, "/"))
+ path_simplify(p, false);
+ if (suppress_root && empty_or_root(p))
p = mfree(p);
- free(*arg);
- *arg = p;
+ free_and_replace(*arg, p);
+
return 0;
}
@@ -729,16 +724,23 @@ char* dirname_malloc(const char *path) {
}
const char *last_path_component(const char *path) {
- /* Finds the last component of the path, preserving the
- * optional trailing slash that signifies a directory.
+
+ /* Finds the last component of the path, preserving the optional trailing slash that signifies a directory.
+ *
* a/b/c → c
* a/b/c/ → c/
+ * x → x
+ * x/ → x/
+ * /y → y
+ * /y/ → y/
* / → /
* // → /
* /foo/a → a
* /foo/a/ → a/
- * This is different than basename, which returns "" when
- * a trailing slash is present.
+ *
+ * Also, the empty string is mapped to itself.
+ *
+ * This is different than basename(), which returns "" when a trailing slash is present.
*/
unsigned l, k;
@@ -879,17 +881,36 @@ bool hidden_or_backup_file(const char *filename) {
bool is_device_path(const char *path) {
- /* Returns true on paths that refer to a device, either in
- * sysfs or in /dev */
+ /* Returns true on paths that likely refer to a device, either by path in sysfs or to something in /dev */
+
+ return PATH_STARTSWITH_SET(path, "/dev/", "/sys/");
+}
+
+bool valid_device_node_path(const char *path) {
+
+ /* Some superficial checks whether the specified path is a valid device node path, all without looking at the
+ * actual device node. */
+
+ if (!PATH_STARTSWITH_SET(path, "/dev/", "/run/systemd/inaccessible/"))
+ return false;
+
+ if (endswith(path, "/")) /* can't be a device node if it ends in a slash */
+ return false;
- return path_startswith(path, "/dev/") ||
- path_startswith(path, "/sys/");
+ return path_is_normalized(path);
}
-bool is_deviceallow_pattern(const char *path) {
- return path_startswith(path, "/dev/") ||
- startswith(path, "block-") ||
- startswith(path, "char-");
+bool valid_device_allow_pattern(const char *path) {
+ assert(path);
+
+ /* Like valid_device_node_path(), but also allows full-subsystem expressions, like DeviceAllow= and DeviceDeny=
+ * accept it */
+
+ if (startswith(path, "block-") ||
+ startswith(path, "char-"))
+ return true;
+
+ return valid_device_node_path(path);
}
int systemd_installation_has_version(const char *root, unsigned minimal_version) {
@@ -925,7 +946,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
if (r < 0)
return r;
- assert_se((c = endswith(path, "*.so")));
+ assert_se(c = endswith(path, "*.so"));
*c = '\0'; /* truncate the glob part */
STRV_FOREACH(name, names) {
@@ -972,3 +993,61 @@ bool dot_or_dot_dot(const char *path) {
return path[2] == 0;
}
+
+bool empty_or_root(const char *root) {
+
+ /* For operations relative to some root directory, returns true if the specified root directory is redundant,
+ * i.e. either / or NULL or the empty string or any equivalent. */
+
+ if (!root)
+ return true;
+
+ return root[strspn(root, "/")] == 0;
+}
+
+int path_simplify_and_warn(
+ char *path,
+ unsigned flag,
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *lvalue) {
+
+ bool absolute, fatal = flag & PATH_CHECK_FATAL;
+
+ assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
+
+ if (!utf8_is_valid(path)) {
+ log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path);
+ return -EINVAL;
+ }
+
+ if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) {
+ absolute = path_is_absolute(path);
+
+ if (!absolute && (flag & PATH_CHECK_ABSOLUTE)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is not absolute%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+
+ if (absolute && (flag & PATH_CHECK_RELATIVE)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is absolute%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+ }
+
+ path_simplify(path, true);
+
+ if (!path_is_normalized(path)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is not normalized%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 73f1769fd9..8277c6b916 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <stdbool.h>
#include <stddef.h>
@@ -28,19 +9,32 @@
#include "string-util.h"
#include "time-util.h"
+#define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin"
+#define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0"
+
+#define PATH_NORMAL_SBIN_BIN(x) x "bin"
+#define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0"
+
#if HAVE_SPLIT_BIN
-# define PATH_SBIN_BIN(x) x "sbin:" x "bin"
+# define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x)
+# define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x)
#else
-# define PATH_SBIN_BIN(x) x "bin"
+# define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x)
+# define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x)
#endif
#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
+#define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/")
#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
+#define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/")
+#define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/")
#if HAVE_SPLIT_USR
# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
+# define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR
#else
# define DEFAULT_PATH DEFAULT_PATH_NORMAL
+# define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR
#endif
bool is_path(const char *p) _pure_;
@@ -50,12 +44,12 @@ char* path_make_absolute(const char *p, const char *prefix);
int safe_getcwd(char **ret);
int path_make_absolute_cwd(const char *p, char **ret);
int path_make_relative(const char *from_dir, const char *to_path, char **_r);
-char* path_kill_slashes(char *path);
char* path_startswith(const char *path, const char *prefix) _pure_;
int path_compare(const char *a, const char *b) _pure_;
bool path_equal(const char *a, const char *b) _pure_;
bool path_equal_or_files_same(const char *a, const char *b, int flags);
char* path_join(const char *root, const char *path, const char *rest);
+char* path_simplify(char *path, bool kill_dots);
static inline bool path_equal_ptr(const char *a, const char *b) {
return !!a == !!b && (!a || path_equal(a, b));
@@ -101,11 +95,11 @@ int mkfs_exists(const char *fstype);
* the tree, to root. Also returns "" (and not "/"!) for the root
* directory. Excludes the specified directory itself */
#define PATH_FOREACH_PREFIX(prefix, path) \
- for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
+ for (char *_slash = ({ path_simplify(strcpy(prefix, path), false); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
#define PATH_FOREACH_PREFIX_MORE(prefix, path) \
- for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
+ for (char *_slash = ({ path_simplify(strcpy(prefix, path), false); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
char *prefix_root(const char *root, const char *path);
@@ -118,7 +112,7 @@ char *prefix_root(const char *root, const char *path);
size_t _l; \
while (_path[0] == '/' && _path[1] == '/') \
_path ++; \
- if (isempty(_root) || path_equal(_root, "/")) \
+ if (empty_or_root(_root)) \
_ret = _path; \
else { \
_l = strlen(_root) + 1 + strlen(_path) + 1; \
@@ -147,7 +141,9 @@ char *file_in_same_dir(const char *path, const char *filename);
bool hidden_or_backup_file(const char *filename) _pure_;
bool is_device_path(const char *path);
-bool is_deviceallow_pattern(const char *path);
+
+bool valid_device_node_path(const char *path);
+bool valid_device_allow_pattern(const char *path);
int systemd_installation_has_version(const char *root, unsigned minimal_version);
@@ -162,3 +158,16 @@ static inline const char *skip_dev_prefix(const char *p) {
return e ?: p;
}
+
+bool empty_or_root(const char *root);
+static inline const char *empty_to_root(const char *path) {
+ return isempty(path) ? "/" : path;
+}
+
+enum {
+ PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */
+ PATH_CHECK_ABSOLUTE = 1 << 1,
+ PATH_CHECK_RELATIVE = 1 << 2,
+};
+
+int path_simplify_and_warn(char *path, unsigned flag, const char *unit, const char *filename, unsigned line, const char *lvalue);
diff --git a/src/basic/prioq.c b/src/basic/prioq.c
index 2a1f1af878..ef28a086d1 100644
--- a/src/basic/prioq.c
+++ b/src/basic/prioq.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
/*
* Priority Queue
diff --git a/src/basic/prioq.h b/src/basic/prioq.h
index a222955dfe..e036175260 100644
--- a/src/basic/prioq.h
+++ b/src/basic/prioq.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "hashmap.h"
diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c
index c5d1fb1d41..add481c2ae 100644
--- a/src/basic/proc-cmdline.c
+++ b/src/basic/proc-cmdline.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
#include <stddef.h>
@@ -204,10 +186,8 @@ int proc_cmdline_get_key(const char *key, unsigned flags, char **value) {
}
}
- if (value) {
- *value = ret;
- ret = NULL;
- }
+ if (value)
+ *value = TAKE_PTR(ret);
return found;
}
diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h
index 16ccfbc2cb..4a9e6e0f62 100644
--- a/src/basic/proc-cmdline.h
+++ b/src/basic/proc-cmdline.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "log.h"
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index e6120af5b6..0a4f917cbd 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <ctype.h>
#include <errno.h>
@@ -30,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/types.h>
@@ -88,20 +71,31 @@ int get_process_state(pid_t pid) {
return (unsigned char) state;
}
-int get_process_comm(pid_t pid, char **name) {
+int get_process_comm(pid_t pid, char **ret) {
+ _cleanup_free_ char *escaped = NULL, *comm = NULL;
const char *p;
int r;
- assert(name);
+ assert(ret);
assert(pid >= 0);
+ escaped = new(char, TASK_COMM_LEN);
+ if (!escaped)
+ return -ENOMEM;
+
p = procfs_file_alloca(pid, "comm");
- r = read_one_line_file(p, name);
+ r = read_one_line_file(p, &comm);
if (r == -ENOENT)
return -ESRCH;
+ if (r < 0)
+ return r;
- return r;
+ /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */
+ cellescape(escaped, TASK_COMM_LEN, comm);
+
+ *ret = TAKE_PTR(escaped);
+ return 0;
}
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
@@ -259,15 +253,10 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
memcpy(ans, "[...]", max_length-1);
ans[max_length-1] = 0;
} else {
- char *e;
-
t[max_length - 6] = 0;
/* Chop off final spaces */
- e = strchr(t, 0);
- while (e > t && isspace(e[-1]))
- e--;
- *e = 0;
+ delete_trailing_chars(t, WHITESPACE);
ans = strjoin("[", t, "...]");
}
@@ -308,7 +297,7 @@ int rename_process(const char name[]) {
* can use PR_SET_NAME, which sets the thread name for the calling thread. */
if (prctl(PR_SET_NAME, name) < 0)
log_debug_errno(errno, "PR_SET_NAME failed: %m");
- if (l > 15) /* Linux process names can be 15 chars at max */
+ if (l >= TASK_COMM_LEN) /* Linux process names can be 15 chars at max */
truncated = true;
/* Second step, change glibc's ID of the process name. */
@@ -623,8 +612,7 @@ int get_process_environ(pid_t pid, char **env) {
} else
outcome[sz] = '\0';
- *env = outcome;
- outcome = NULL;
+ *env = TAKE_PTR(outcome);
return 0;
}
@@ -753,14 +741,17 @@ int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
/*
* Return values:
- * < 0 : wait_for_terminate_with_timeout() failed to get the state of the
- * process, the process timed out, the process was terminated by a
- * signal, or failed for an unknown reason.
+ *
+ * < 0 : wait_for_terminate_with_timeout() failed to get the state of the process, the process timed out, the process
+ * was terminated by a signal, or failed for an unknown reason.
+ *
* >=0 : The process terminated normally with no failures.
*
- * Success is indicated by a return value of zero, a timeout is indicated
- * by ETIMEDOUT, and all other child failure states are indicated by error
- * is indicated by a non-zero value.
+ * Success is indicated by a return value of zero, a timeout is indicated by ETIMEDOUT, and all other child failure
+ * states are indicated by error is indicated by a non-zero value.
+ *
+ * This call assumes SIGCHLD has been blocked already, in particular before the child to wait for has been forked off
+ * to remain entirely race-free.
*/
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
sigset_t mask;
@@ -894,7 +885,7 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
do {
char line[LINE_MAX];
- unsigned i;
+ size_t i;
for (i = 0; i < sizeof(line)-1; i++) {
int c;
@@ -1358,6 +1349,16 @@ int safe_fork_full(
}
}
+ if (FLAGS_SET(flags, FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE)) {
+
+ /* Optionally, make sure we never propagate mounts to the host. */
+
+ if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
+ log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (flags & FORK_CLOSE_ALL_FDS) {
/* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
log_close();
@@ -1389,9 +1390,9 @@ int safe_fork_full(
return 0;
}
-int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *ret_pid, const char *path, ...) {
+int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) {
bool stdout_is_tty, stderr_is_tty;
- unsigned n, i;
+ size_t n, i;
va_list ap;
char **l;
int r;
@@ -1447,7 +1448,7 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
va_end(ap);
/* Allocate strv */
- l = alloca(sizeof(char *) * (n + 1));
+ l = newa(char*, n + 1);
/* Fill in arguments */
va_start(ap, path);
@@ -1459,6 +1460,15 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
_exit(EXIT_FAILURE);
}
+int set_oom_score_adjust(int value) {
+ char t[DECIMAL_STR_MAX(int)];
+
+ sprintf(t, "%i", value);
+
+ return write_string_file("/proc/self/oom_score_adj", t,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
@@ -1466,7 +1476,7 @@ static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_IDLE] = "idle"
};
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, IOPRIO_N_CLASSES);
static const char *const sigchld_code_table[] = {
[CLD_EXITED] = "exited",
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 5170adec7b..a5bb072b25 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <errno.h>
#include <sched.h>
@@ -64,8 +45,8 @@ int get_process_ppid(pid_t pid, pid_t *ppid);
int wait_for_terminate(pid_t pid, siginfo_t *status);
typedef enum WaitFlags {
- WAIT_LOG_ABNORMAL = 1U << 0,
- WAIT_LOG_NON_ZERO_EXIT_STATUS = 1U << 1,
+ WAIT_LOG_ABNORMAL = 1 << 0,
+ WAIT_LOG_NON_ZERO_EXIT_STATUS = 1 << 1,
/* A shortcut for requesting the most complete logging */
WAIT_LOG = WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS,
@@ -168,14 +149,15 @@ void reset_cached_pid(void);
int must_be_root(void);
typedef enum ForkFlags {
- FORK_RESET_SIGNALS = 1U << 0,
- FORK_CLOSE_ALL_FDS = 1U << 1,
- FORK_DEATHSIG = 1U << 2,
- FORK_NULL_STDIO = 1U << 3,
- FORK_REOPEN_LOG = 1U << 4,
- FORK_LOG = 1U << 5,
- FORK_WAIT = 1U << 6,
- FORK_NEW_MOUNTNS = 1U << 7,
+ FORK_RESET_SIGNALS = 1 << 0,
+ FORK_CLOSE_ALL_FDS = 1 << 1,
+ FORK_DEATHSIG = 1 << 2,
+ FORK_NULL_STDIO = 1 << 3,
+ FORK_REOPEN_LOG = 1 << 4,
+ FORK_LOG = 1 << 5,
+ FORK_WAIT = 1 << 6,
+ FORK_NEW_MOUNTNS = 1 << 7,
+ FORK_MOUNTNS_SLAVE = 1 << 8,
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
@@ -184,7 +166,9 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
return safe_fork_full(name, NULL, 0, flags, ret_pid);
}
-int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *pid, const char *path, ...);
+int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...);
+
+int set_oom_score_adjust(int value);
#if SIZEOF_PID_T == 4
/* The highest possibly (theoretic) pid_t value on this architecture. */
@@ -204,3 +188,11 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *p
#endif
assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX)
+
+/* Like TAKE_PTR() but for child PIDs, resetting them to 0 */
+#define TAKE_PID(pid) \
+ ({ \
+ pid_t _pid_ = (pid); \
+ (pid) = 0; \
+ _pid_; \
+ })
diff --git a/src/basic/random-util.c b/src/basic/random-util.c
index 7457815fa2..91481559db 100644
--- a/src/basic/random-util.c
+++ b/src/basic/random-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <elf.h>
#include <errno.h>
@@ -48,7 +30,7 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
static int have_syscall = -1;
_cleanup_close_ int fd = -1;
- unsigned already_done = 0;
+ size_t already_done = 0;
int r;
/* Gathers some randomness from the kernel. This call will never block. If
@@ -59,7 +41,7 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
* for us. */
/* Use the getrandom() syscall unless we know we don't have it. */
- if (have_syscall != 0) {
+ if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
r = getrandom(p, n, GRND_NONBLOCK);
if (r > 0) {
have_syscall = true;
@@ -122,7 +104,6 @@ void initialize_srand(void) {
#endif
x = 0;
-
x ^= (unsigned) now(CLOCK_REALTIME);
x ^= (unsigned) gettid();
diff --git a/src/basic/random-util.h b/src/basic/random-util.h
index dd8701515e..9a103f0e94 100644
--- a/src/basic/random-util.h
+++ b/src/basic/random-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/src/basic/ratelimit.c b/src/basic/ratelimit.c
index 5b684e261a..4e04e04426 100644
--- a/src/basic/ratelimit.c
+++ b/src/basic/ratelimit.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/time.h>
@@ -27,7 +8,7 @@
/* Modelled after Linux' lib/ratelimit.c by Dave Young
* <hidave.darkstar@gmail.com>, which is licensed GPLv2. */
-bool ratelimit_test(RateLimit *r) {
+bool ratelimit_below(RateLimit *r) {
usec_t ts;
assert(r);
diff --git a/src/basic/ratelimit.h b/src/basic/ratelimit.h
index 19acf9c854..de91def28d 100644
--- a/src/basic/ratelimit.h
+++ b/src/basic/ratelimit.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "time-util.h"
@@ -56,4 +37,4 @@ typedef struct RateLimit {
_r->begin = 0; \
} while (false)
-bool ratelimit_test(RateLimit *r);
+bool ratelimit_below(RateLimit *r);
diff --git a/src/basic/raw-clone.h b/src/basic/raw-clone.h
index 8c95380305..1f134ba7f2 100644
--- a/src/basic/raw-clone.h
+++ b/src/basic/raw-clone.h
@@ -2,24 +2,10 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2016 Michael Karcher
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Michael Karcher
***/
+#include <errno.h>
#include <sched.h>
#include <sys/syscall.h>
@@ -51,27 +37,36 @@ static inline pid_t raw_clone(unsigned long flags) {
/* On s390/s390x and cris the order of the first and second arguments
* of the raw clone() system call is reversed. */
ret = (pid_t) syscall(__NR_clone, NULL, flags);
-#elif defined(__sparc__) && defined(__arch64__)
+#elif defined(__sparc__)
{
/**
- * sparc64 always returns the other process id in %o0, and
+ * sparc always returns the other process id in %o0, and
* a boolean flag whether this is the child or the parent in
* %o1. Inline assembly is needed to get the flag returned
* in %o1.
*/
- int in_child, child_pid;
+ int in_child, child_pid, error;
- asm volatile("mov %2, %%g1\n\t"
- "mov %3, %%o0\n\t"
+ asm volatile("mov %3, %%g1\n\t"
+ "mov %4, %%o0\n\t"
"mov 0 , %%o1\n\t"
+#if defined(__arch64__)
"t 0x6d\n\t"
+#else
+ "t 0x10\n\t"
+#endif
+ "addx %%g0, 0, %2\n\t"
"mov %%o1, %0\n\t"
"mov %%o0, %1" :
- "=r"(in_child), "=r"(child_pid) :
+ "=r"(in_child), "=r"(child_pid), "=r"(error) :
"i"(__NR_clone), "r"(flags) :
- "%o1", "%o0", "%g1" );
+ "%o1", "%o0", "%g1" "cc" );
- ret = in_child ? 0 : child_pid;
+ if (error) {
+ errno = child_pid;
+ ret = -1;
+ } else
+ ret = in_child ? 0 : child_pid;
}
#else
ret = (pid_t) syscall(__NR_clone, flags, NULL);
diff --git a/src/basic/reboot-util.h b/src/basic/reboot-util.h
index d4aa441290..d459333efc 100644
--- a/src/basic/reboot-util.h
+++ b/src/basic/reboot-util.h
@@ -4,9 +4,9 @@
int update_reboot_parameter_and_warn(const char *parameter);
typedef enum RebootFlags {
- REBOOT_LOG = 1U << 0, /* log about what we are going to do and all errors */
- REBOOT_DRY_RUN = 1U << 1, /* return 0 right before actually doing the reboot */
- REBOOT_FALLBACK = 1U << 2, /* fallback to plain reboot() if argument-based reboot doesn't work, isn't configured or doesn't apply otherwise */
+ REBOOT_LOG = 1 << 0, /* log about what we are going to do and all errors */
+ REBOOT_DRY_RUN = 1 << 1, /* return 0 right before actually doing the reboot */
+ REBOOT_FALLBACK = 1 << 2, /* fallback to plain reboot() if argument-based reboot doesn't work, isn't configured or doesn't apply otherwise */
} RebootFlags;
int reboot_with_parameter(RebootFlags flags);
diff --git a/src/basic/refcnt.h b/src/basic/refcnt.h
index ae2e446d6c..d2be6086d2 100644
--- a/src/basic/refcnt.h
+++ b/src/basic/refcnt.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
/* A type-safe atomic refcounter.
*
* DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c
index c73ed9777e..fd2b5c104f 100644
--- a/src/basic/replace-var.c
+++ b/src/basic/replace-var.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stddef.h>
diff --git a/src/basic/replace-var.h b/src/basic/replace-var.h
index 3d5906198e..e6a489feee 100644
--- a/src/basic/replace-var.h
+++ b/src/basic/replace-var.h
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
char *replace_var(const char *text, char *(*lookup)(const char *variable, void *userdata), void *userdata);
diff --git a/src/basic/rlimit-util.c b/src/basic/rlimit-util.c
index 00648211d3..be1ba615ec 100644
--- a/src/basic/rlimit-util.c
+++ b/src/basic/rlimit-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <sys/resource.h>
@@ -46,6 +28,11 @@ int setrlimit_closest(int resource, const struct rlimit *rlim) {
if (getrlimit(resource, &highest) < 0)
return -errno;
+ /* If the hard limit is unbounded anyway, then the EPERM had other reasons, let's propagate the original EPERM
+ * then */
+ if (highest.rlim_max == RLIM_INFINITY)
+ return -EPERM;
+
fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
@@ -55,6 +42,32 @@ int setrlimit_closest(int resource, const struct rlimit *rlim) {
return 0;
}
+int setrlimit_closest_all(const struct rlimit *const *rlim, int *which_failed) {
+ int i, r;
+
+ assert(rlim);
+
+ /* On failure returns the limit's index that failed in *which_failed, but only if non-NULL */
+
+ for (i = 0; i < _RLIMIT_MAX; i++) {
+ if (!rlim[i])
+ continue;
+
+ r = setrlimit_closest(i, rlim[i]);
+ if (r < 0) {
+ if (which_failed)
+ *which_failed = i;
+
+ return r;
+ }
+ }
+
+ if (which_failed)
+ *which_failed = -1;
+
+ return 0;
+}
+
static int rlimit_parse_u64(const char *val, rlim_t *ret) {
uint64_t u;
int r;
@@ -302,22 +315,48 @@ int rlimit_format(const struct rlimit *rl, char **ret) {
}
static const char* const rlimit_table[_RLIMIT_MAX] = {
- [RLIMIT_CPU] = "LimitCPU",
- [RLIMIT_FSIZE] = "LimitFSIZE",
- [RLIMIT_DATA] = "LimitDATA",
- [RLIMIT_STACK] = "LimitSTACK",
- [RLIMIT_CORE] = "LimitCORE",
- [RLIMIT_RSS] = "LimitRSS",
- [RLIMIT_NOFILE] = "LimitNOFILE",
- [RLIMIT_AS] = "LimitAS",
- [RLIMIT_NPROC] = "LimitNPROC",
- [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
- [RLIMIT_LOCKS] = "LimitLOCKS",
- [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
- [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
- [RLIMIT_NICE] = "LimitNICE",
- [RLIMIT_RTPRIO] = "LimitRTPRIO",
- [RLIMIT_RTTIME] = "LimitRTTIME"
+ [RLIMIT_AS] = "AS",
+ [RLIMIT_CORE] = "CORE",
+ [RLIMIT_CPU] = "CPU",
+ [RLIMIT_DATA] = "DATA",
+ [RLIMIT_FSIZE] = "FSIZE",
+ [RLIMIT_LOCKS] = "LOCKS",
+ [RLIMIT_MEMLOCK] = "MEMLOCK",
+ [RLIMIT_MSGQUEUE] = "MSGQUEUE",
+ [RLIMIT_NICE] = "NICE",
+ [RLIMIT_NOFILE] = "NOFILE",
+ [RLIMIT_NPROC] = "NPROC",
+ [RLIMIT_RSS] = "RSS",
+ [RLIMIT_RTPRIO] = "RTPRIO",
+ [RLIMIT_RTTIME] = "RTTIME",
+ [RLIMIT_SIGPENDING] = "SIGPENDING",
+ [RLIMIT_STACK] = "STACK",
};
DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
+
+int rlimit_from_string_harder(const char *s) {
+ const char *suffix;
+
+ /* The official prefix */
+ suffix = startswith(s, "RLIMIT_");
+ if (suffix)
+ return rlimit_from_string(suffix);
+
+ /* Our own unit file setting prefix */
+ suffix = startswith(s, "Limit");
+ if (suffix)
+ return rlimit_from_string(suffix);
+
+ return rlimit_from_string(s);
+}
+
+void rlimit_free_all(struct rlimit **rl) {
+ int i;
+
+ if (!rl)
+ return;
+
+ for (i = 0; i < _RLIMIT_MAX; i++)
+ rl[i] = mfree(rl[i]);
+}
diff --git a/src/basic/rlimit-util.h b/src/basic/rlimit-util.h
index 4494b89c76..c2ea6f846b 100644
--- a/src/basic/rlimit-util.h
+++ b/src/basic/rlimit-util.h
@@ -1,37 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/resource.h>
#include "macro.h"
const char *rlimit_to_string(int i) _const_;
int rlimit_from_string(const char *s) _pure_;
+int rlimit_from_string_harder(const char *s) _pure_;
int setrlimit_closest(int resource, const struct rlimit *rlim);
+int setrlimit_closest_all(const struct rlimit * const *rlim, int *which_failed);
int rlimit_parse_one(int resource, const char *val, rlim_t *ret);
int rlimit_parse(int resource, const char *val, struct rlimit *ret);
int rlimit_format(const struct rlimit *rl, char **ret);
+void rlimit_free_all(struct rlimit **rl);
+
#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index 2839f37cd9..54f6dc2059 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -26,6 +8,7 @@
#include <sys/statfs.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "cgroup-util.h"
#include "dirent-util.h"
@@ -62,13 +45,15 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
}
if (is_physical_fs(&sfs)) {
- /* We refuse to clean physical file systems
- * with this call, unless explicitly
- * requested. This is extra paranoia just to
- * be sure we never ever remove non-state
- * data */
+ /* We refuse to clean physical file systems with this call,
+ * unless explicitly requested. This is extra paranoia just
+ * to be sure we never ever remove non-state data. */
+ _cleanup_free_ char *path = NULL;
+
+ (void) fd_get_path(fd, &path);
+ log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.",
+ strna(path));
- log_error("Attempted to remove disk file system, and we can't allow that.");
safe_close(fd);
return -EPERM;
}
@@ -184,11 +169,11 @@ int rm_rf(const char *path, RemoveFlags flags) {
* call. This is extra paranoia to never cause a really
* seriously broken system. */
if (path_equal_or_files_same(path, "/", AT_SYMLINK_NOFOLLOW)) {
- log_error("Attempted to remove entire root file system, and we can't allow that.");
+ log_error("Attempted to remove entire root file system (\"%s\"), and we can't allow that.", path);
return -EPERM;
}
- if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) {
+ if (FLAGS_SET(flags, REMOVE_SUBVOLUME | REMOVE_ROOT | REMOVE_PHYSICAL)) {
/* Try to remove as subvolume first */
r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
if (r >= 0)
@@ -202,7 +187,6 @@ int rm_rf(const char *path, RemoveFlags flags) {
fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
if (fd < 0) {
-
if (!IN_SET(errno, ENOTDIR, ELOOP))
return -errno;
@@ -211,7 +195,7 @@ int rm_rf(const char *path, RemoveFlags flags) {
return -errno;
if (is_physical_fs(&s)) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
+ log_error("Attempted to remove files from a disk file system under \"%s\", refusing.", path);
return -EPERM;
}
}
diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h
index 6e63d3feab..0a2d7f0358 100644
--- a/src/basic/rm-rf.h
+++ b/src/basic/rm-rf.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/stat.h>
#include "util.h"
diff --git a/src/basic/securebits-util.c b/src/basic/securebits-util.c
index 441d386f9e..ad091f6d95 100644
--- a/src/basic/securebits-util.c
+++ b/src/basic/securebits-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Yu Watanabe
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
@@ -48,8 +30,7 @@ int secure_bits_to_string_alloc(int i, char **s) {
if (len != 0)
str[len - 1] = '\0';
- *s = str;
- str = NULL;
+ *s = TAKE_PTR(str);
return 0;
}
diff --git a/src/basic/securebits-util.h b/src/basic/securebits-util.h
index 069d215488..10a221d6a0 100644
--- a/src/basic/securebits-util.h
+++ b/src/basic/securebits-util.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Yu Watanabe
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "securebits.h"
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index 0c6e99b1d7..e15bd7e1fa 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <malloc.h>
@@ -34,10 +16,12 @@
#endif
#include "alloc-util.h"
+#include "fd-util.h"
#include "log.h"
#include "macro.h"
#include "path-util.h"
#include "selinux-util.h"
+#include "stdio-util.h"
#include "time-util.h"
#include "util.h"
@@ -51,7 +35,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
static int cached_use = -1;
static struct selabel_handle *label_hnd = NULL;
-#define log_enforcing(...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, errno, __VA_ARGS__)
+#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)
+#define log_enforcing_errno(r, ...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, r, __VA_ARGS__)
#endif
bool mac_selinux_use(void) {
@@ -89,7 +74,7 @@ int mac_selinux_init(void) {
label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
if (!label_hnd) {
- log_enforcing("Failed to initialize SELinux context: %m");
+ log_enforcing_errno(errno, "Failed to initialize SELinux context: %m");
r = security_getenforce() == 1 ? -errno : 0;
} else {
char timespan[FORMAT_TIMESPAN_MAX];
@@ -120,9 +105,12 @@ void mac_selinux_finish(void) {
#endif
}
-int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int mac_selinux_fix(const char *path, LabelFixFlags flags) {
#if HAVE_SELINUX
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_freecon_ char* fcon = NULL;
+ _cleanup_close_ int fd = -1;
struct stat st;
int r;
@@ -132,37 +120,55 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
if (!label_hnd)
return 0;
- r = lstat(path, &st);
- if (r >= 0) {
- _cleanup_freecon_ char* fcon = NULL;
+ /* Open the file as O_PATH, to pin it while we determine and adjust the label */
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
+ if (fd < 0) {
+ if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT)
+ return 0;
- r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
+ return -errno;
+ }
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ if (selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode) < 0) {
+ r = -errno;
/* If there's no label to set, then exit without warning */
- if (r < 0 && errno == ENOENT)
+ if (r == -ENOENT)
return 0;
- if (r >= 0) {
- r = lsetfilecon_raw(path, fcon);
-
- /* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == EOPNOTSUPP)
- return 0;
- }
+ goto fail;
}
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ if (setfilecon_raw(procfs_path, fcon) < 0) {
+ _cleanup_freecon_ char *oldcon = NULL;
+
+ r = -errno;
+
+ /* If the FS doesn't support labels, then exit without warning */
+ if (r == -EOPNOTSUPP)
return 0;
- if (ignore_erofs && errno == EROFS)
+ /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
+ if (r == -EROFS && (flags & LABEL_IGNORE_EROFS))
return 0;
- log_enforcing("Unable to fix SELinux security context of %s: %m", path);
- if (security_getenforce() == 1)
- return -errno;
+ /* If the old label is identical to the new one, suppress any kind of error */
+ if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon))
+ return 0;
+
+ goto fail;
}
+
+ return 0;
+
+fail:
+ log_enforcing_errno(r, "Unable to fix SELinux security context of %s: %m", path);
+ if (security_getenforce() == 1)
+ return r;
#endif
return 0;
@@ -178,7 +184,7 @@ int mac_selinux_apply(const char *path, const char *label) {
assert(label);
if (setfilecon(path, label) < 0) {
- log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path);
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
if (security_getenforce() > 0)
return -errno;
}
@@ -304,7 +310,6 @@ char* mac_selinux_free(char *label) {
if (!mac_selinux_use())
return NULL;
-
freecon(label);
#endif
@@ -339,12 +344,12 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
if (errno == ENOENT)
return 0;
- log_enforcing("Failed to determine SELinux security context for %s: %m", path);
+ log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
} else {
if (setfscreatecon_raw(filecon) >= 0)
return 0; /* Success! */
- log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, path);
}
if (security_getenforce() > 0)
@@ -375,7 +380,7 @@ int mac_selinux_create_socket_prepare(const char *label) {
assert(label);
if (setsockcreatecon(label) < 0) {
- log_enforcing("Failed to set SELinux security context %s for sockets: %m", label);
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
if (security_getenforce() == 1)
return -errno;
@@ -447,13 +452,13 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
if (errno == ENOENT)
goto skipped;
- log_enforcing("Failed to determine SELinux security context for %s: %m", path);
+ log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
if (security_getenforce() > 0)
return -errno;
} else {
if (setfscreatecon_raw(fcon) < 0) {
- log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
if (security_getenforce() > 0)
return -errno;
} else
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
index 9780dca81e..08314057fb 100644
--- a/src/basic/selinux-util.h
+++ b/src/basic/selinux-util.h
@@ -1,30 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "macro.h"
+#include "label.h"
bool mac_selinux_use(void);
void mac_selinux_retest(void);
@@ -32,7 +14,7 @@ void mac_selinux_retest(void);
int mac_selinux_init(void);
void mac_selinux_finish(void);
-int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+int mac_selinux_fix(const char *path, LabelFixFlags flags);
int mac_selinux_apply(const char *path, const char *label);
int mac_selinux_get_create_label_from_exe(const char *exe, char **label);
diff --git a/src/basic/set.c b/src/basic/set.c
deleted file mode 100644
index e554e825eb..0000000000
--- a/src/basic/set.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "set.h"
-
-int set_make(Set **ret, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS, void *add, ...) {
- _cleanup_set_free_ Set *s = NULL;
- int r;
-
- assert(ret);
-
- s = set_new(hash_ops HASHMAP_DEBUG_PASS_ARGS);
- if (!s)
- return -ENOMEM;
-
- if (add) {
- va_list ap;
-
- r = set_put(s, add);
- if (r < 0)
- return r;
-
- va_start(ap, add);
-
- for (;;) {
- void *arg = va_arg(ap, void*);
-
- if (!arg)
- break;
-
- r = set_put(s, arg);
- if (r < 0) {
- va_end(ap);
- return r;
- }
- }
-
- va_end(ap);
- }
-
- *ret = s;
- s = NULL;
-
- return 0;
-}
diff --git a/src/basic/set.h b/src/basic/set.h
index 156ab4b081..664713810d 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "extract-word.h"
#include "hashmap.h"
#include "macro.h"
@@ -149,5 +130,3 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
#define _cleanup_set_free_ _cleanup_(set_freep)
#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
-
-int set_make(Set **ret, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS, void *add, ...);
diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c
index 2416929e36..70afba6bcf 100644
--- a/src/basic/sigbus.c
+++ b/src/basic/sigbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <signal.h>
diff --git a/src/basic/sigbus.h b/src/basic/sigbus.h
index 90b0c9632e..459e19fcaa 100644
--- a/src/basic/sigbus.h
+++ b/src/basic/sigbus.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
void sigbus_install(void);
void sigbus_reset(void);
diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c
index 27caabe471..fb8a63fb9a 100644
--- a/src/basic/signal-util.c
+++ b/src/basic/signal-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdarg.h>
@@ -242,36 +224,65 @@ const char *signal_to_string(int signo) {
}
int signal_from_string(const char *s) {
- int signo;
- int offset = 0;
- unsigned u;
+ const char *p;
+ int signo, r;
+ /* Check that the input is a signal number. */
+ if (safe_atoi(s, &signo) >= 0) {
+ if (SIGNAL_VALID(signo))
+ return signo;
+ else
+ return -ERANGE;
+ }
+
+ /* Drop "SIG" prefix. */
+ if (startswith(s, "SIG"))
+ s += 3;
+
+ /* Check that the input is a signal name. */
signo = __signal_from_string(s);
if (signo > 0)
return signo;
- if (startswith(s, "RTMIN+")) {
- s += 6;
- offset = SIGRTMIN;
- }
- if (safe_atou(s, &u) >= 0) {
- signo = (int) u + offset;
- if (SIGNAL_VALID(signo))
- return signo;
+ /* Check that the input is RTMIN or
+ * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
+ p = startswith(s, "RTMIN");
+ if (p) {
+ if (*p == '\0')
+ return SIGRTMIN;
+ if (*p != '+')
+ return -EINVAL;
+
+ r = safe_atoi(p, &signo);
+ if (r < 0)
+ return r;
+
+ if (signo < 0 || signo > SIGRTMAX - SIGRTMIN)
+ return -ERANGE;
+
+ return signo + SIGRTMIN;
}
- return -EINVAL;
-}
-int signal_from_string_try_harder(const char *s) {
- int signo;
- assert(s);
+ /* Check that the input is RTMAX or
+ * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
+ p = startswith(s, "RTMAX");
+ if (p) {
+ if (*p == '\0')
+ return SIGRTMAX;
+ if (*p != '-')
+ return -EINVAL;
+
+ r = safe_atoi(p, &signo);
+ if (r < 0)
+ return r;
- signo = signal_from_string(s);
- if (signo <= 0)
- if (startswith(s, "SIG"))
- return signal_from_string(s+3);
+ if (signo > 0 || signo < SIGRTMIN - SIGRTMAX)
+ return -ERANGE;
- return signo;
+ return signo + SIGRTMAX;
+ }
+
+ return -EINVAL;
}
void nop_signal_handler(int sig) {
diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h
index f6c3396ebe..92f2804cd2 100644
--- a/src/basic/signal-util.h
+++ b/src/basic/signal-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <signal.h>
#include "macro.h"
@@ -37,8 +18,6 @@ int sigprocmask_many(int how, sigset_t *old, ...);
const char *signal_to_string(int i) _const_;
int signal_from_string(const char *s) _pure_;
-int signal_from_string_try_harder(const char *s);
-
void nop_signal_handler(int sig);
static inline void block_signals_reset(sigset_t *ss) {
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
index f0018f013f..9d31b7717f 100644
--- a/src/basic/smack-util.c
+++ b/src/basic/smack-util.c
@@ -1,38 +1,26 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Intel Corporation
+ Copyright © 2013 Intel Corporation
Author: Auke Kok <auke-jan.h.kok@intel.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
+#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include <unistd.h>
#include "alloc-util.h"
+#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
#include "path-util.h"
#include "process-util.h"
#include "smack-util.h"
+#include "stdio-util.h"
#include "string-table.h"
#include "xattr-util.h"
@@ -134,7 +122,10 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
return r;
}
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int mac_smack_fix(const char *path, LabelFixFlags flags) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int fd = -1;
+ const char *label;
struct stat st;
int r;
@@ -143,50 +134,72 @@ int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
if (!mac_smack_use())
return 0;
+ /* Path must be in /dev. Note that this check is pretty sloppy, as we might be called with non-normalized paths
+ * and hence not detect all cases of /dev. */
+
+ if (path_is_absolute(path)) {
+ if (!path_startswith(path, "/dev"))
+ return 0;
+ } else {
+ _cleanup_free_ char *cwd = NULL;
+
+ r = safe_getcwd(&cwd);
+ if (r < 0)
+ return r;
+
+ if (!path_startswith(cwd, "/dev"))
+ return 0;
+ }
+
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
+ if (fd < 0) {
+ if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT)
+ return 0;
+
+ return -errno;
+ }
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
/*
- * Path must be in /dev and must exist
+ * Label directories and character devices "*".
+ * Label symlinks "_".
+ * Don't change anything else.
*/
- if (!path_startswith(path, "/dev"))
+
+ if (S_ISDIR(st.st_mode))
+ label = SMACK_STAR_LABEL;
+ else if (S_ISLNK(st.st_mode))
+ label = SMACK_FLOOR_LABEL;
+ else if (S_ISCHR(st.st_mode))
+ label = SMACK_STAR_LABEL;
+ else
return 0;
- r = lstat(path, &st);
- if (r >= 0) {
- const char *label;
-
- /*
- * Label directories and character devices "*".
- * Label symlinks "_".
- * Don't change anything else.
- */
-
- if (S_ISDIR(st.st_mode))
- label = SMACK_STAR_LABEL;
- else if (S_ISLNK(st.st_mode))
- label = SMACK_FLOOR_LABEL;
- else if (S_ISCHR(st.st_mode))
- label = SMACK_STAR_LABEL;
- else
- return 0;
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ if (setxattr(procfs_path, "security.SMACK64", label, strlen(label), 0) < 0) {
+ _cleanup_free_ char *old_label = NULL;
- r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
+ r = -errno;
/* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == EOPNOTSUPP)
+ if (r == -EOPNOTSUPP)
return 0;
- }
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
+ /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
+ if (r == -EROFS && (flags & LABEL_IGNORE_EROFS))
return 0;
- if (ignore_erofs && errno == EROFS)
+ /* If the old label is identical to the new one, suppress any kind of error */
+ if (getxattr_malloc(procfs_path, "security.SMACK64", &old_label, false) >= 0 &&
+ streq(old_label, label))
return 0;
- r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
+ return log_debug_errno(r, "Unable to fix SMACK label of %s: %m", path);
}
- return r;
+ return 0;
}
int mac_smack_copy(const char *dest, const char *src) {
@@ -232,7 +245,7 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
return 0;
}
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int mac_smack_fix(const char *path, LabelFixFlags flags) {
return 0;
}
diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h
index e4d46d7736..fd59787ecb 100644
--- a/src/basic/smack-util.h
+++ b/src/basic/smack-util.h
@@ -2,48 +2,34 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Intel Corporation
+ Copyright © 2013 Intel Corporation
Author: Auke Kok <auke-jan.h.kok@intel.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
#include <sys/types.h>
+#include "label.h"
#include "macro.h"
#define SMACK_FLOOR_LABEL "_"
#define SMACK_STAR_LABEL "*"
typedef enum SmackAttr {
- SMACK_ATTR_ACCESS = 0,
- SMACK_ATTR_EXEC = 1,
- SMACK_ATTR_MMAP = 2,
- SMACK_ATTR_TRANSMUTE = 3,
- SMACK_ATTR_IPIN = 4,
- SMACK_ATTR_IPOUT = 5,
+ SMACK_ATTR_ACCESS,
+ SMACK_ATTR_EXEC,
+ SMACK_ATTR_MMAP,
+ SMACK_ATTR_TRANSMUTE,
+ SMACK_ATTR_IPIN,
+ SMACK_ATTR_IPOUT,
_SMACK_ATTR_MAX,
_SMACK_ATTR_INVALID = -1,
} SmackAttr;
bool mac_smack_use(void);
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+int mac_smack_fix(const char *path, LabelFixFlags flags);
const char* smack_attr_to_string(SmackAttr i) _const_;
SmackAttr smack_attr_from_string(const char *s) _pure_;
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index 97f3ebe2af..35e14e567c 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <netinet/in.h>
diff --git a/src/basic/socket-protocol-list.c b/src/basic/socket-protocol-list.c
index 9ab93d1c7e..8041b84958 100644
--- a/src/basic/socket-protocol-list.c
+++ b/src/basic/socket-protocol-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/in.h>
#include <string.h>
diff --git a/src/basic/socket-protocol-list.h b/src/basic/socket-protocol-list.h
index 12fd053382..458904dbb3 100644
--- a/src/basic/socket-protocol-list.h
+++ b/src/basic/socket-protocol-list.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
const char *socket_protocol_to_name(int id);
int socket_protocol_from_name(const char *name);
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index b91b093132..a913102e13 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <errno.h>
@@ -677,7 +659,6 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
return -EOPNOTSUPP;
}
-
*ret = p;
return 0;
}
@@ -804,7 +785,7 @@ static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIN
DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
-SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *n) {
+SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) {
int r;
r = parse_boolean(n);
@@ -985,8 +966,7 @@ int getpeersec(int fd, char **ret) {
if (isempty(s))
return -EOPNOTSUPP;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
@@ -1018,8 +998,7 @@ int getpeergroups(int fd, gid_t **ret) {
if ((socklen_t) (int) n != n)
return -E2BIG;
- *ret = d;
- d = NULL;
+ *ret = TAKE_PTR(d);
return (int) n;
}
@@ -1079,7 +1058,7 @@ int receive_one_fd(int transport_fd, int flags) {
* combination with send_one_fd().
*/
- if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
+ if (recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags) < 0)
return -errno;
CMSG_FOREACH(cmsg, &mh) {
@@ -1142,7 +1121,6 @@ int flush_accept(int fd) {
};
int r;
-
/* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
for (;;) {
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 2e5694b126..8e23cf2dbd 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <netinet/ether.h>
#include <netinet/in.h>
#include <stdbool.h>
@@ -129,7 +110,7 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
-SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *s);
+SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s);
int netlink_family_to_string_alloc(int b, char **s);
int netlink_family_from_string(const char *s) _pure_;
diff --git a/src/basic/special.h b/src/basic/special.h
index c058b1d852..379a3d7979 100644
--- a/src/basic/special.h
+++ b/src/basic/special.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#define SPECIAL_DEFAULT_TARGET "default.target"
/* Shutdown targets */
@@ -37,6 +18,7 @@
#define SPECIAL_SUSPEND_TARGET "suspend.target"
#define SPECIAL_HIBERNATE_TARGET "hibernate.target"
#define SPECIAL_HYBRID_SLEEP_TARGET "hybrid-sleep.target"
+#define SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET "suspend-then-hibernate.target"
/* Special boot targets */
#define SPECIAL_RESCUE_TARGET "rescue.target"
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
index 67705947aa..07154e25bb 100644
--- a/src/basic/stat-util.c
+++ b/src/basic/stat-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -145,32 +127,6 @@ int path_is_read_only_fs(const char *path) {
return false;
}
-int path_is_os_tree(const char *path) {
- int r;
-
- assert(path);
-
- /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
- * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
- * the case where just the os-release file is missing. */
- if (laccess(path, F_OK) < 0)
- return -errno;
-
- /* We use /usr/lib/os-release as flag file if something is an OS */
- r = chase_symlinks("/usr/lib/os-release", path, CHASE_PREFIX_ROOT, NULL);
- if (r == -ENOENT) {
-
- /* Also check for the old location in /etc, just in case. */
- r = chase_symlinks("/etc/os-release", path, CHASE_PREFIX_ROOT, NULL);
- if (r == -ENOENT)
- return 0; /* We got nothing */
- }
- if (r < 0)
- return r;
-
- return 1;
-}
-
int files_same(const char *filea, const char *fileb, int flags) {
struct stat a, b;
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
index 4b941f6104..f8014ed30b 100644
--- a/src/basic/stat-util.h
+++ b/src/basic/stat-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <sys/stat.h>
@@ -48,7 +29,6 @@ int null_or_empty_path(const char *fn);
int null_or_empty_fd(int fd);
int path_is_read_only_fs(const char *path);
-int path_is_os_tree(const char *path);
int files_same(const char *filea, const char *fileb, int flags);
diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h
index d3fed365d8..73c03274c7 100644
--- a/src/basic/stdio-util.h
+++ b/src/basic/stdio-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <printf.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c
index bc3e56cf71..e2ed776a09 100644
--- a/src/basic/strbuf.c
+++ b/src/basic/strbuf.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
@@ -24,6 +6,7 @@
#include "alloc-util.h"
#include "strbuf.h"
+#include "util.h"
/*
* Strbuf stores given strings in a single continuous allocated memory
@@ -46,33 +29,31 @@
struct strbuf *strbuf_new(void) {
struct strbuf *str;
- str = new0(struct strbuf, 1);
+ str = new(struct strbuf, 1);
if (!str)
return NULL;
+ *str = (struct strbuf) {
+ .buf = new0(char, 1),
+ .root = new0(struct strbuf_node, 1),
+ .len = 1,
+ .nodes_count = 1,
+ };
+ if (!str->buf || !str->root) {
+ free(str->buf);
+ free(str->root);
+ return mfree(str);
+ }
- str->buf = new0(char, 1);
- if (!str->buf)
- goto err;
- str->len = 1;
-
- str->root = new0(struct strbuf_node, 1);
- if (!str->root)
- goto err;
- str->nodes_count = 1;
return str;
-err:
- free(str->buf);
- free(str->root);
- return mfree(str);
}
-static void strbuf_node_cleanup(struct strbuf_node *node) {
+static struct strbuf_node* strbuf_node_cleanup(struct strbuf_node *node) {
size_t i;
for (i = 0; i < node->children_count; i++)
strbuf_node_cleanup(node->children[i].child);
free(node->children);
- free(node);
+ return mfree(node);
}
/* clean up trie data, leave only the string buffer */
@@ -80,16 +61,12 @@ void strbuf_complete(struct strbuf *str) {
if (!str)
return;
if (str->root)
- strbuf_node_cleanup(str->root);
- str->root = NULL;
+ str->root = strbuf_node_cleanup(str->root);
}
/* clean up everything */
void strbuf_cleanup(struct strbuf *str) {
- if (!str)
- return;
- if (str->root)
- strbuf_node_cleanup(str->root);
+ strbuf_complete(str);
free(str->buf);
free(str);
}
@@ -138,13 +115,15 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
return -EINVAL;
/* search string; start from last character to find possibly matching tails */
- if (len == 0)
- return 0;
+
str->in_count++;
+ if (len == 0) {
+ str->dedup_count++;
+ return 0;
+ }
str->in_len += len;
node = str->root;
- c = s[len-1];
for (depth = 0; depth <= len; depth++) {
struct strbuf_child_entry search;
@@ -158,15 +137,11 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
c = s[len - 1 - depth];
- /* bsearch is not allowed on a NULL sequence */
- if (node->children_count == 0)
- break;
-
/* lookup child node */
search.c = c;
- child = bsearch(&search, node->children, node->children_count,
- sizeof(struct strbuf_child_entry),
- (__compar_fn_t) strbuf_children_cmp);
+ child = bsearch_safe(&search, node->children, node->children_count,
+ sizeof(struct strbuf_child_entry),
+ (__compar_fn_t) strbuf_children_cmp);
if (!child)
break;
node = child->child;
@@ -183,11 +158,13 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
str->buf[str->len++] = '\0';
/* new node */
- node_child = new0(struct strbuf_node, 1);
+ node_child = new(struct strbuf_node, 1);
if (!node_child)
return -ENOMEM;
- node_child->value_off = off;
- node_child->value_len = len;
+ *node_child = (struct strbuf_node) {
+ .value_off = off,
+ .value_len = len,
+ };
/* extend array, add new entry, sort for bisection */
child = reallocarray(node->children, node->children_count + 1, sizeof(struct strbuf_child_entry));
diff --git a/src/basic/strbuf.h b/src/basic/strbuf.h
index d5888a06dc..75ed30b05b 100644
--- a/src/basic/strbuf.h
+++ b/src/basic/strbuf.h
@@ -1,29 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
+#include "macro.h"
+
struct strbuf {
char *buf;
size_t len;
@@ -53,3 +37,4 @@ struct strbuf *strbuf_new(void);
ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len);
void strbuf_complete(struct strbuf *str);
void strbuf_cleanup(struct strbuf *str);
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_cleanup);
diff --git a/src/basic/string-table.c b/src/basic/string-table.c
index d4b7c69bdc..34931b03d8 100644
--- a/src/basic/string-table.c
+++ b/src/basic/string-table.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "string-table.h"
#include "string-util.h"
diff --git a/src/basic/string-table.h b/src/basic/string-table.h
index 4306b90f46..9bd7879355 100644
--- a/src/basic/string-table.h
+++ b/src/basic/string-table.h
@@ -2,25 +2,6 @@
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
@@ -90,16 +71,13 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
return (type) -1; \
} \
-
#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)
#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope)
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
@@ -111,10 +89,24 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
/* For string conversions where numbers are also acceptable */
#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
+
+#define DUMP_STRING_TABLE(name,type,max) \
+ do { \
+ type _k; \
+ flockfile(stdout); \
+ for (_k = 0; _k < (max); _k++) { \
+ const char *_t; \
+ _t = name##_to_string(_k); \
+ if (!_t) \
+ continue; \
+ fputs_unlocked(_t, stdout); \
+ fputc_unlocked('\n', stdout); \
+ } \
+ funlockfile(stdout); \
+ } while(false)
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index 9f2c01d864..0a40683493 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdarg.h>
@@ -27,12 +9,15 @@
#include <string.h>
#include "alloc-util.h"
+#include "escape.h"
#include "gunicode.h"
+#include "locale-util.h"
#include "macro.h"
#include "string-util.h"
#include "terminal-util.h"
#include "utf8.h"
#include "util.h"
+#include "fileio.h"
int strcmp_ptr(const char *a, const char *b) {
@@ -279,23 +264,12 @@ char *strjoin_real(const char *x, ...) {
}
char *strstrip(char *s) {
- char *e;
-
if (!s)
return NULL;
- /* Drops trailing whitespace. Modifies the string in
- * place. Returns pointer to first non-space character */
-
- s += strspn(s, WHITESPACE);
-
- for (e = strchr(s, 0); e > s; e --)
- if (!strchr(WHITESPACE, e[-1]))
- break;
-
- *e = 0;
+ /* Drops trailing whitespace. Modifies the string in place. Returns pointer to first non-space character */
- return s;
+ return delete_trailing_chars(skip_leading_chars(s, WHITESPACE), WHITESPACE);
}
char *delete_chars(char *s, const char *bad) {
@@ -464,94 +438,154 @@ bool string_has_cc(const char *p, const char *ok) {
return false;
}
+static int write_ellipsis(char *buf, bool unicode) {
+ if (unicode || is_locale_utf8()) {
+ buf[0] = 0xe2; /* tri-dot ellipsis: … */
+ buf[1] = 0x80;
+ buf[2] = 0xa6;
+ } else {
+ buf[0] = '.';
+ buf[1] = '.';
+ buf[2] = '.';
+ }
+
+ return 3;
+}
+
static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
- size_t x;
- char *r;
+ size_t x, need_space, suffix_len;
+ char *t;
assert(s);
assert(percent <= 100);
- assert(new_length >= 3);
+ assert(new_length != (size_t) -1);
- if (old_length <= 3 || old_length <= new_length)
+ if (old_length <= new_length)
return strndup(s, old_length);
- r = new0(char, new_length+3);
- if (!r)
+ /* Special case short ellipsations */
+ switch (new_length) {
+
+ case 0:
+ return strdup("");
+
+ case 1:
+ if (is_locale_utf8())
+ return strdup("…");
+ else
+ return strdup(".");
+
+ case 2:
+ if (!is_locale_utf8())
+ return strdup("..");
+
+ break;
+
+ default:
+ break;
+ }
+
+ /* Calculate how much space the ellipsis will take up. If we are in UTF-8 mode we only need space for one
+ * character ("…"), otherwise for three characters ("..."). Note that in both cases we need 3 bytes of storage,
+ * either for the UTF-8 encoded character or for three ASCII characters. */
+ need_space = is_locale_utf8() ? 1 : 3;
+
+ t = new(char, new_length+3);
+ if (!t)
return NULL;
- x = (new_length * percent) / 100;
+ assert(new_length >= need_space);
- if (x > new_length - 3)
- x = new_length - 3;
+ x = ((new_length - need_space) * percent + 50) / 100;
+ assert(x <= new_length - need_space);
- memcpy(r, s, x);
- r[x] = 0xe2; /* tri-dot ellipsis: … */
- r[x+1] = 0x80;
- r[x+2] = 0xa6;
- memcpy(r + x + 3,
- s + old_length - (new_length - x - 1),
- new_length - x - 1);
+ memcpy(t, s, x);
+ write_ellipsis(t + x, false);
+ suffix_len = new_length - x - need_space;
+ memcpy(t + x + 3, s + old_length - suffix_len, suffix_len);
+ *(t + x + 3 + suffix_len) = '\0';
- return r;
+ return t;
}
char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
- size_t x;
- char *e;
+ size_t x, k, len, len2;
const char *i, *j;
- unsigned k, len, len2;
+ char *e;
int r;
+ /* Note that 'old_length' refers to bytes in the string, while 'new_length' refers to character cells taken up
+ * on screen. This distinction doesn't matter for ASCII strings, but it does matter for non-ASCII UTF-8
+ * strings.
+ *
+ * Ellipsation is done in a locale-dependent way:
+ * 1. If the string passed in is fully ASCII and the current locale is not UTF-8, three dots are used ("...")
+ * 2. Otherwise, a unicode ellipsis is used ("…")
+ *
+ * In other words: you'll get a unicode ellipsis as soon as either the string contains non-ASCII characters or
+ * the current locale is UTF-8.
+ */
+
assert(s);
assert(percent <= 100);
if (new_length == (size_t) -1)
return strndup(s, old_length);
- assert(new_length >= 3);
+ if (new_length == 0)
+ return strdup("");
- /* if no multibyte characters use ascii_ellipsize_mem for speed */
- if (ascii_is_valid(s))
+ /* If no multibyte characters use ascii_ellipsize_mem for speed */
+ if (ascii_is_valid_n(s, old_length))
return ascii_ellipsize_mem(s, old_length, new_length, percent);
- if (old_length <= 3 || old_length <= new_length)
- return strndup(s, old_length);
-
- x = (new_length * percent) / 100;
-
- if (x > new_length - 3)
- x = new_length - 3;
+ x = ((new_length - 1) * percent) / 100;
+ assert(x <= new_length - 1);
k = 0;
- for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
+ for (i = s; i < s + old_length; i = utf8_next_char(i)) {
char32_t c;
+ int w;
r = utf8_encoded_to_unichar(i, &c);
if (r < 0)
return NULL;
- k += unichar_iswide(c) ? 2 : 1;
- }
- if (k > x) /* last character was wide and went over quota */
- x++;
+ w = unichar_iswide(c) ? 2 : 1;
+ if (k + w <= x)
+ k += w;
+ else
+ break;
+ }
- for (j = s + old_length; k < new_length && j > i; ) {
+ for (j = s + old_length; j > i; ) {
char32_t c;
+ int w;
+ const char *jj;
- j = utf8_prev_char(j);
- r = utf8_encoded_to_unichar(j, &c);
+ jj = utf8_prev_char(j);
+ r = utf8_encoded_to_unichar(jj, &c);
if (r < 0)
return NULL;
- k += unichar_iswide(c) ? 2 : 1;
+
+ w = unichar_iswide(c) ? 2 : 1;
+ if (k + w <= new_length) {
+ k += w;
+ j = jj;
+ } else
+ break;
}
assert(i <= j);
/* we don't actually need to ellipsize */
if (i == j)
- return memdup(s, old_length + 1);
+ return memdup_suffix0(s, old_length);
- /* make space for ellipsis */
- j = utf8_next_char(j);
+ /* make space for ellipsis, if possible */
+ if (j < s + old_length)
+ j = utf8_next_char(j);
+ else if (i > s)
+ i = utf8_prev_char(i);
len = i - s;
len2 = s + old_length - j;
@@ -565,21 +599,81 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
*/
memcpy(e, s, len);
- e[len] = 0xe2; /* tri-dot ellipsis: … */
- e[len + 1] = 0x80;
- e[len + 2] = 0xa6;
-
- memcpy(e + len + 3, j, len2 + 1);
+ write_ellipsis(e + len, true);
+ memcpy(e + len + 3, j, len2);
+ *(e + len + 3 + len2) = '\0';
return e;
}
-char *ellipsize(const char *s, size_t length, unsigned percent) {
+char *cellescape(char *buf, size_t len, const char *s) {
+ /* Escape and ellipsize s into buffer buf of size len. Only non-control ASCII
+ * characters are copied as they are, everything else is escaped. The result
+ * is different then if escaping and ellipsization was performed in two
+ * separate steps, because each sequence is either stored in full or skipped.
+ *
+ * This function should be used for logging about strings which expected to
+ * be plain ASCII in a safe way.
+ *
+ * An ellipsis will be used if s is too long. It was always placed at the
+ * very end.
+ */
- if (length == (size_t) -1)
- return strdup(s);
+ size_t i = 0, last_char_width[4] = {}, k = 0, j;
+
+ assert(len > 0); /* at least a terminating NUL */
+
+ for (;;) {
+ char four[4];
+ int w;
+
+ if (*s == 0) /* terminating NUL detected? then we are done! */
+ goto done;
+
+ w = cescape_char(*s, four);
+ if (i + w + 1 > len) /* This character doesn't fit into the buffer anymore? In that case let's
+ * ellipsize at the previous location */
+ break;
+
+ /* OK, there was space, let's add this escaped character to the buffer */
+ memcpy(buf + i, four, w);
+ i += w;
+
+ /* And remember its width in the ring buffer */
+ last_char_width[k] = w;
+ k = (k + 1) % 4;
+
+ s++;
+ }
+
+ /* Ellipsation is necessary. This means we might need to truncate the string again to make space for 4
+ * characters ideally, but the buffer is shorter than that in the first place take what we can get */
+ for (j = 0; j < ELEMENTSOF(last_char_width); j++) {
- return ellipsize_mem(s, strlen(s), length, percent);
+ if (i + 4 <= len) /* nice, we reached our space goal */
+ break;
+
+ k = k == 0 ? 3 : k - 1;
+ if (last_char_width[k] == 0) /* bummer, we reached the beginning of the strings */
+ break;
+
+ assert(i >= last_char_width[k]);
+ i -= last_char_width[k];
+ }
+
+ if (i + 4 <= len) /* yay, enough space */
+ i += write_ellipsis(buf + i, false);
+ else if (i + 3 <= len) { /* only space for ".." */
+ buf[i++] = '.';
+ buf[i++] = '.';
+ } else if (i + 2 <= len) /* only space for a single "." */
+ buf[i++] = '.';
+ else
+ assert(i + 1 <= len);
+
+ done:
+ buf[i] = '\0';
+ return buf;
}
bool nulstr_contains(const char *nulstr, const char *needle) {
@@ -664,7 +758,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
enum {
STATE_OTHER,
STATE_ESCAPE,
- STATE_BRACKET
+ STATE_CSI,
+ STATE_CSO,
} state = STATE_OTHER;
char *obuf = NULL;
size_t osz = 0, isz, shift[2] = {};
@@ -673,7 +768,17 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
assert(ibuf);
assert(*ibuf);
- /* Strips ANSI color and replaces TABs by 8 spaces */
+ /* This does three things:
+ *
+ * 1. Replaces TABs by 8 spaces
+ * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
+ * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
+ *
+ * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as are any
+ * other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the
+ * most basic formatting noise, but nothing else.
+ *
+ * Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
isz = _isz ? *_isz : strlen(*ibuf);
@@ -708,8 +813,11 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
fputc('\x1B', f);
advance_offsets(i - *ibuf, highlight, shift, 1);
break;
- } else if (*i == '[') {
- state = STATE_BRACKET;
+ } else if (*i == '[') { /* ANSI CSI */
+ state = STATE_CSI;
+ begin = i + 1;
+ } else if (*i == ']') { /* ANSI CSO */
+ state = STATE_CSO;
begin = i + 1;
} else {
fputc('\x1B', f);
@@ -720,10 +828,10 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
break;
- case STATE_BRACKET:
+ case STATE_CSI:
- if (i >= *ibuf + isz || /* EOT */
- (!(*i >= '0' && *i <= '9') && !IN_SET(*i, ';', 'm'))) {
+ if (i >= *ibuf + isz || /* EOT … */
+ !strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */
fputc('\x1B', f);
fputc('[', f);
advance_offsets(i - *ibuf, highlight, shift, 2);
@@ -731,11 +839,26 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
i = begin-1;
} else if (*i == 'm')
state = STATE_OTHER;
+
+ break;
+
+ case STATE_CSO:
+
+ if (i >= *ibuf + isz || /* EOT … */
+ (*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */
+ fputc('\x1B', f);
+ fputc(']', f);
+ advance_offsets(i - *ibuf, highlight, shift, 2);
+ state = STATE_OTHER;
+ i = begin-1;
+ } else if (*i == '\a')
+ state = STATE_OTHER;
+
break;
}
}
- if (ferror(f)) {
+ if (fflush_and_check(f) < 0) {
fclose(f);
return mfree(obuf);
}
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index 08eda4fce0..c0cc4e78d7 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <stdbool.h>
#include <stddef.h>
@@ -71,7 +52,7 @@ static inline const char *empty_to_null(const char *p) {
return isempty(p) ? NULL : p;
}
-static inline const char *strdash_if_empty(const char *str) {
+static inline const char *empty_to_dash(const char *str) {
return isempty(str) ? "-" : str;
}
@@ -122,7 +103,7 @@ char *strjoin_real(const char *x, ...) _sentinel_;
const char *_appendees_[] = { a, __VA_ARGS__ }; \
char *_d_, *_p_; \
size_t _len_ = 0; \
- unsigned _i_; \
+ size_t _i_; \
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
_len_ += strlen(_appendees_[_i_]); \
_p_ = _d_ = alloca(_len_ + 1); \
@@ -169,7 +150,14 @@ static inline bool _pure_ in_charset(const char *s, const char* charset) {
bool string_has_cc(const char *p, const char *ok) _pure_;
char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent);
-char *ellipsize(const char *s, size_t length, unsigned percent);
+static inline char *ellipsize(const char *s, size_t length, unsigned percent) {
+ return ellipsize_mem(s, strlen(s), length, percent);
+}
+
+char *cellescape(char *buf, size_t len, const char *s);
+
+/* This limit is arbitrary, enough to give some idea what the string contains */
+#define CELLESCAPE_DEFAULT_LENGTH 64
bool nulstr_contains(const char *nulstr, const char *needle);
@@ -222,3 +210,21 @@ static inline size_t strlen_ptr(const char *s) {
return strlen(s);
}
+
+/* Like startswith(), but operates on arbitrary memory blocks */
+static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
+ size_t n;
+
+ assert(token);
+
+ n = strlen(token);
+ if (sz < n)
+ return NULL;
+
+ assert(p);
+
+ if (memcmp(p, token, n) != 0)
+ return NULL;
+
+ return (uint8_t*) p + n;
+}
diff --git a/src/basic/strv.c b/src/basic/strv.c
index e80ff4a62c..b3716233b5 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fnmatch.h>
@@ -120,8 +102,8 @@ char **strv_copy(char * const *l) {
return r;
}
-unsigned strv_length(char * const *l) {
- unsigned n = 0;
+size_t strv_length(char * const *l) {
+ size_t n = 0;
if (!l)
return 0;
@@ -134,8 +116,8 @@ unsigned strv_length(char * const *l) {
char **strv_new_ap(const char *x, va_list ap) {
const char *s;
- char **a;
- unsigned n = 0, i = 0;
+ _cleanup_strv_free_ char **a = NULL;
+ size_t n = 0, i = 0;
va_list aq;
/* As a special trick we ignore all listed strings that equal
@@ -165,7 +147,7 @@ char **strv_new_ap(const char *x, va_list ap) {
if (x != STRV_IGNORE) {
a[i] = strdup(x);
if (!a[i])
- goto fail;
+ return NULL;
i++;
}
@@ -176,7 +158,7 @@ char **strv_new_ap(const char *x, va_list ap) {
a[i] = strdup(s);
if (!a[i])
- goto fail;
+ return NULL;
i++;
}
@@ -184,11 +166,7 @@ char **strv_new_ap(const char *x, va_list ap) {
a[i] = NULL;
- return a;
-
-fail:
- strv_free(a);
- return NULL;
+ return TAKE_PTR(a);
}
char **strv_new(const char *x, ...) {
@@ -270,7 +248,7 @@ int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
char **strv_split(const char *s, const char *separator) {
const char *word, *state;
size_t l;
- unsigned n, i;
+ size_t n, i;
char **r;
assert(s);
@@ -300,7 +278,7 @@ char **strv_split(const char *s, const char *separator) {
char **strv_split_newlines(const char *s) {
char **l;
- unsigned n;
+ size_t n;
assert(s);
@@ -341,8 +319,7 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
if (!GREEDY_REALLOC(l, allocated, n + 2))
return -ENOMEM;
- l[n++] = word;
- word = NULL;
+ l[n++] = TAKE_PTR(word);
l[n] = NULL;
}
@@ -353,8 +330,7 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
return -ENOMEM;
}
- *t = l;
- l = NULL;
+ *t = TAKE_PTR(l);
return (int) n;
}
@@ -395,7 +371,7 @@ char *strv_join(char **l, const char *separator) {
int strv_push(char ***l, char *value) {
char **c;
- unsigned n, m;
+ size_t n, m;
if (!value)
return 0;
@@ -420,7 +396,7 @@ int strv_push(char ***l, char *value) {
int strv_push_pair(char ***l, char *a, char *b) {
char **c;
- unsigned n, m;
+ size_t n, m;
if (!a && !b)
return 0;
@@ -446,9 +422,9 @@ int strv_push_pair(char ***l, char *a, char *b) {
return 0;
}
-int strv_insert(char ***l, unsigned position, char *value) {
+int strv_insert(char ***l, size_t position, char *value) {
char **c;
- unsigned n, m, i;
+ size_t n, m, i;
if (!value)
return 0;
@@ -616,7 +592,7 @@ char **strv_parse_nulstr(const char *s, size_t l) {
*/
const char *p;
- unsigned c = 0, i = 0;
+ size_t c = 0, i = 0;
char **v;
assert(s || l <= 0);
@@ -780,7 +756,7 @@ int strv_extendf(char ***l, const char *format, ...) {
}
char **strv_reverse(char **l) {
- unsigned n, i;
+ size_t n, i;
n = strv_length(l);
if (n <= 1)
diff --git a/src/basic/strv.h b/src/basic/strv.h
index f169ac5d4f..51d03db940 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <fnmatch.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -45,7 +26,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase);
void strv_clear(char **l);
char **strv_copy(char * const *l);
-unsigned strv_length(char * const *l) _pure_;
+size_t strv_length(char * const *l) _pure_;
int strv_extend_strv(char ***a, char **b, bool filter_duplicates);
int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
@@ -54,7 +35,7 @@ int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
int strv_extend_front(char ***l, const char *value);
int strv_push(char ***l, char *value);
int strv_push_pair(char ***l, char *a, char *b);
-int strv_insert(char ***l, unsigned position, char *value);
+int strv_insert(char ***l, size_t position, char *value);
static inline int strv_push_prepend(char ***l, char *value) {
return strv_insert(l, 0, value);
@@ -126,7 +107,7 @@ void strv_print(char **l);
if (!first) \
_l = (char**) &first; \
else { \
- unsigned _n; \
+ size_t _n; \
va_list _ap; \
\
_n = 1; \
diff --git a/src/basic/strxcpyx.c b/src/basic/strxcpyx.c
index b440a9a725..6277f56b80 100644
--- a/src/basic/strxcpyx.c
+++ b/src/basic/strxcpyx.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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/>.
-***/
/*
* Concatenates/copies strings. In any case, terminates in all cases
diff --git a/src/basic/strxcpyx.h b/src/basic/strxcpyx.h
index 0554454fd2..458f9f2568 100644
--- a/src/basic/strxcpyx.h
+++ b/src/basic/strxcpyx.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stddef.h>
diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c
index 4f4e2354b6..21461fa581 100644
--- a/src/basic/syslog-util.c
+++ b/src/basic/syslog-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
#include <syslog.h>
diff --git a/src/basic/syslog-util.h b/src/basic/syslog-util.h
index 8f44e3f8ef..8f419e8151 100644
--- a/src/basic/syslog-util.h
+++ b/src/basic/syslog-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
int log_facility_unshifted_to_string_alloc(int i, char **s);
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index eacfd14677..f4af0e6522 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -1,45 +1,30 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <linux/kd.h>
+#include <linux/tiocl.h>
+#include <linux/vt.h>
+#include <poll.h>
+#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sysmacros.h>
#include <sys/time.h>
-#include <linux/kd.h>
-#include <linux/tiocl.h>
-#include <linux/vt.h>
-#include <poll.h>
-#include <signal.h>
-#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <termios.h>
#include <unistd.h>
#include "alloc-util.h"
+#include "copy.h"
+#include "def.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -47,6 +32,7 @@
#include "io-util.h"
#include "log.h"
#include "macro.h"
+#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
@@ -496,10 +482,7 @@ int acquire_terminal(
fd = safe_close(fd);
}
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
int release_terminal(void) {
@@ -707,10 +690,9 @@ int vtnr_from_tty(const char *tty) {
tty = active;
}
- if (tty == active) {
- *ret = active;
- active = NULL;
- } else {
+ if (tty == active)
+ *ret = TAKE_PTR(active);
+ else {
char *tmp;
tmp = strdup(tty);
@@ -778,8 +760,7 @@ int get_kernel_consoles(char ***ret) {
goto fallback;
}
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
return 0;
@@ -788,8 +769,7 @@ fallback:
if (r < 0)
return r;
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
return 0;
}
@@ -899,8 +879,17 @@ void reset_terminal_feature_caches(void) {
}
bool on_tty(void) {
+
+ /* We check both stdout and stderr, so that situations where pipes on the shell are used are reliably
+ * recognized, regardless if only the output or the errors are piped to some place. Since on_tty() is generally
+ * used to default to a safer, non-interactive, non-color mode of operation it's probably good to be defensive
+ * here, and check for both. Note that we don't check for STDIN_FILENO, because it should fine to use fancy
+ * terminal functionality when outputting stuff, even if the input is piped to us. */
+
if (cached_on_tty < 0)
- cached_on_tty = isatty(STDOUT_FILENO) > 0;
+ cached_on_tty =
+ isatty(STDOUT_FILENO) > 0 &&
+ isatty(STDERR_FILENO) > 0;
return cached_on_tty;
}
@@ -1288,3 +1277,175 @@ int vt_reset_keyboard(int fd) {
return 0;
}
+
+static bool urlify_enabled(void) {
+ static int cached_urlify_enabled = -1;
+
+ /* Unfortunately 'less' doesn't support links like this yet 😭, hence let's disable this as long as there's a
+ * pager in effect. Let's drop this check as soon as less got fixed a and enough time passed so that it's safe
+ * to assume that a link-enabled 'less' version has hit most installations. */
+
+ if (cached_urlify_enabled < 0) {
+ int val;
+
+ val = getenv_bool("SYSTEMD_URLIFY");
+ if (val >= 0)
+ cached_urlify_enabled = val;
+ else
+ cached_urlify_enabled = colors_enabled() && !pager_have();
+ }
+
+ return cached_urlify_enabled;
+}
+
+int terminal_urlify(const char *url, const char *text, char **ret) {
+ char *n;
+
+ assert(url);
+
+ /* Takes an URL and a pretty string and formats it as clickable link for the terminal. See
+ * https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda for details. */
+
+ if (isempty(text))
+ text = url;
+
+ if (urlify_enabled())
+ n = strjoin("\x1B]8;;", url, "\a", text, "\x1B]8;;\a");
+ else
+ n = strdup(text);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
+}
+
+int terminal_urlify_path(const char *path, const char *text, char **ret) {
+ _cleanup_free_ char *absolute = NULL;
+ struct utsname u;
+ const char *url;
+ int r;
+
+ assert(path);
+
+ /* Much like terminal_urlify() above, but takes a file system path as input
+ * and turns it into a proper file:// URL first. */
+
+ if (isempty(path))
+ return -EINVAL;
+
+ if (isempty(text))
+ text = path;
+
+ if (!urlify_enabled()) {
+ char *n;
+
+ n = strdup(text);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
+ }
+
+ if (uname(&u) < 0)
+ return -errno;
+
+ if (!path_is_absolute(path)) {
+ r = path_make_absolute_cwd(path, &absolute);
+ if (r < 0)
+ return r;
+
+ path = absolute;
+ }
+
+ /* As suggested by https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda, let's include the local
+ * hostname here. Note that we don't use gethostname_malloc() or gethostname_strict() since we are interested
+ * in the raw string the kernel has set, whatever it may be, under the assumption that terminals are not overly
+ * careful with validating the strings either. */
+
+ url = strjoina("file://", u.nodename, path);
+
+ return terminal_urlify(url, text, ret);
+}
+
+static int cat_file(const char *filename, bool newline) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *urlified = NULL;
+ int r;
+
+ f = fopen(filename, "re");
+ if (!f)
+ return -errno;
+
+ r = terminal_urlify_path(filename, NULL, &urlified);
+ if (r < 0)
+ return r;
+
+ printf("%s%s# %s%s\n",
+ newline ? "\n" : "",
+ ansi_highlight_blue(),
+ urlified,
+ ansi_normal());
+ fflush(stdout);
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read \"%s\": %m", filename);
+ if (r == 0)
+ break;
+
+ puts(line);
+ }
+
+ return 0;
+}
+
+int cat_files(const char *file, char **dropins, CatFlags flags) {
+ char **path;
+ int r;
+
+ if (file) {
+ r = cat_file(file, false);
+ if (r == -ENOENT && (flags & CAT_FLAGS_MAIN_FILE_OPTIONAL))
+ printf("%s# config file %s not found%s\n",
+ ansi_highlight_magenta(),
+ file,
+ ansi_normal());
+ else if (r < 0)
+ return log_warning_errno(r, "Failed to cat %s: %m", file);
+ }
+
+ STRV_FOREACH(path, dropins) {
+ r = cat_file(*path, file || path != dropins);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to cat %s: %m", *path);
+ }
+
+ return 0;
+}
+
+void print_separator(void) {
+
+ /* Outputs a separator line that resolves to whitespace when copied from the terminal. We do that by outputting
+ * one line filled with spaces with ANSI underline set, followed by a second (empty) line. */
+
+ if (underline_enabled()) {
+ size_t i, c;
+
+ c = columns();
+
+ flockfile(stdout);
+ fputs_unlocked(ANSI_UNDERLINE, stdout);
+
+ for (i = 0; i < c; i++)
+ fputc_unlocked(' ', stdout);
+
+ fputs_unlocked(ANSI_NORMAL "\n\n", stdout);
+ funlockfile(stdout);
+ } else
+ fputs("\n\n", stdout);
+}
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index b57157e3bb..c0bd0e67a6 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
@@ -80,16 +61,16 @@ int open_terminal(const char *name, int mode);
/* Flags for tweaking the way we become the controlling process of a terminal. */
typedef enum AcquireTerminalFlags {
/* Try to become the controlling process of the TTY. If we can't return -EPERM. */
- ACQUIRE_TERMINAL_TRY = 0,
+ ACQUIRE_TERMINAL_TRY = 0,
/* Tell the kernel to forcibly make us the controlling process of the TTY. Returns -EPERM if the kernel doesn't allow that. */
- ACQUIRE_TERMINAL_FORCE = 1,
+ ACQUIRE_TERMINAL_FORCE = 1,
/* If we can't become the controlling process of the TTY right-away, then wait until we can. */
- ACQUIRE_TERMINAL_WAIT = 2,
+ ACQUIRE_TERMINAL_WAIT = 2,
/* Pick one of the above, and then OR this flag in, in order to request permissive behaviour, if we can't become controlling process then don't mind */
- ACQUIRE_TERMINAL_PERMISSIVE = 4,
+ ACQUIRE_TERMINAL_PERMISSIVE = 1 << 2,
} AcquireTerminalFlags;
int acquire_terminal(const char *name, AcquireTerminalFlags flags, usec_t timeout);
@@ -133,22 +114,20 @@ bool dev_console_colors_enabled(void);
#define DEFINE_ANSI_FUNC(name, NAME) \
static inline const char *ansi_##name(void) { \
return colors_enabled() ? ANSI_##NAME : ""; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#define DEFINE_ANSI_FUNC_UNDERLINE(name, NAME, REPLACEMENT) \
static inline const char *ansi_##name(void) { \
return underline_enabled() ? ANSI_##NAME : \
colors_enabled() ? ANSI_##REPLACEMENT : ""; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
+ }
DEFINE_ANSI_FUNC(highlight, HIGHLIGHT);
DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED);
DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN);
DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW);
DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
DEFINE_ANSI_FUNC(normal, NORMAL);
DEFINE_ANSI_FUNC_UNDERLINE(underline, UNDERLINE, NORMAL);
@@ -172,3 +151,14 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
int vt_default_utf8(void);
int vt_reset_keyboard(int fd);
+
+int terminal_urlify(const char *url, const char *text, char **ret);
+int terminal_urlify_path(const char *path, const char *text, char **ret);
+
+typedef enum CatFlags {
+ CAT_FLAGS_MAIN_FILE_OPTIONAL = 1 << 0,
+} CatFlags;
+
+int cat_files(const char *file, char **dropins, CatFlags flags);
+
+void print_separator(void);
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index 4a341e208f..fe201c398d 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <limits.h>
@@ -34,11 +16,13 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "io-util.h"
#include "log.h"
#include "macro.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -293,8 +277,11 @@ static char *format_timestamp_internal(
return NULL; /* Timestamp is unset */
/* Let's not format times with years > 9999 */
- if (t > USEC_TIMESTAMP_FORMATTABLE_MAX)
- return NULL;
+ if (t > USEC_TIMESTAMP_FORMATTABLE_MAX) {
+ assert(l >= strlen("--- XXXX-XX-XX XX:XX:XX") + 1);
+ strcpy(buf, "--- XXXX-XX-XX XX:XX:XX");
+ return buf;
+ }
sec = (time_t) (t / USEC_PER_SEC); /* Round down */
@@ -447,7 +434,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
{ "us", 1 },
};
- unsigned i;
+ size_t i;
char *p = buf;
bool something = false;
@@ -492,7 +479,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
/* Let's see if we should shows this in dot notation */
if (t < USEC_PER_MINUTE && b > 0) {
usec_t cc;
- int j;
+ signed char j;
j = 0;
for (cc = table[i].usec; cc > 1; cc /= 10)
@@ -625,10 +612,9 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
time_t x;
usec_t x_usec, plus = 0, minus = 0, ret;
int r, weekday = -1, dst = -1;
- unsigned i;
+ size_t i;
- /*
- * Allowed syntaxes:
+ /* Allowed syntaxes:
*
* 2012-09-22 16:34:22
* 2012-09-22 16:34 (seconds will be set to 0)
@@ -642,7 +628,6 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
* +5min
* -5days
* @2147483647 (seconds since epoch)
- *
*/
assert(t);
@@ -701,10 +686,10 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
tzset();
/* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
- * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
- * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
- * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
- * support arbitrary timezone specifications. */
+ * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
+ * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
+ * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
+ * support arbitrary timezone specifications. */
for (j = 0; j <= 1; j++) {
@@ -890,7 +875,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
int r;
last_space = strrchr(t, ' ');
- if (last_space != NULL && timezone_is_valid(last_space + 1))
+ if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG))
tz = last_space + 1;
if (!tz || endswith_no_case(t, " UTC"))
@@ -916,10 +901,10 @@ int parse_timestamp(const char *t, usec_t *usec) {
tzset();
/* If there is a timezone that matches the tzname fields, leave the parsing to the implementation.
- * Otherwise just cut it off */
+ * Otherwise just cut it off. */
with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]);
- /*cut off the timezone if we dont need it*/
+ /* Cut off the timezone if we dont need it. */
if (with_tz)
t = strndupa(t, last_space - t);
@@ -973,7 +958,7 @@ static char* extract_multiplier(char *p, usec_t *multiplier) {
{ "us", 1ULL },
{ "µs", 1ULL },
};
- unsigned i;
+ size_t i;
for (i = 0; i < ELEMENTSOF(table); i++) {
char *e;
@@ -1147,8 +1132,8 @@ int parse_nsec(const char *t, nsec_t *nsec) {
for (;;) {
long long l, z = 0;
+ size_t n = 0, i;
char *e;
- unsigned i, n = 0;
p += strspn(p, WHITESPACE);
@@ -1283,16 +1268,17 @@ int get_timezones(char ***ret) {
} else if (errno != ENOENT)
return -errno;
- *ret = zones;
- zones = NULL;
+ *ret = TAKE_PTR(zones);
return 0;
}
-bool timezone_is_valid(const char *name) {
+bool timezone_is_valid(const char *name, int log_level) {
bool slash = false;
const char *p, *t;
- struct stat st;
+ _cleanup_close_ int fd = -1;
+ char buf[4];
+ int r;
if (isempty(name))
return false;
@@ -1320,12 +1306,34 @@ bool timezone_is_valid(const char *name) {
if (slash)
return false;
+ if (p - name >= PATH_MAX)
+ return false;
+
t = strjoina("/usr/share/zoneinfo/", name);
- if (stat(t, &st) < 0)
+
+ fd = open(t, O_RDONLY|O_CLOEXEC);
+ if (fd < 0) {
+ log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t);
+ return false;
+ }
+
+ r = fd_verify_regular(fd);
+ if (r < 0) {
+ log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t);
+ return false;
+ }
+
+ r = loop_read_exact(fd, buf, 4, false);
+ if (r < 0) {
+ log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t);
return false;
+ }
- if (!S_ISREG(st.st_mode))
+ /* Magic from tzfile(5) */
+ if (memcmp(buf, "TZif", 4) != 0) {
+ log_full(log_level, "Timezone file '%s' has wrong magic bytes", t);
return false;
+ }
return true;
}
@@ -1396,7 +1404,7 @@ int get_timezone(char **tz) {
if (!e)
return -EINVAL;
- if (!timezone_is_valid(e))
+ if (!timezone_is_valid(e, LOG_DEBUG))
return -EINVAL;
z = strdup(e);
@@ -1453,3 +1461,27 @@ bool in_utc_timezone(void) {
return timezone == 0 && daylight == 0;
}
+
+int time_change_fd(void) {
+
+ /* We only care for the cancellation event, hence we set the timeout to the latest possible value. */
+ static const struct itimerspec its = {
+ .it_value.tv_sec = TIME_T_MAX,
+ };
+
+ _cleanup_close_ int fd;
+
+ assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
+
+ /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever CLOCK_REALTIME makes a jump relative to
+ * CLOCK_MONOTONIC. */
+
+ fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0)
+ return -errno;
+
+ return TAKE_FD(fd);
+}
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index a8c5a8375b..344f2dc52e 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
@@ -141,7 +122,7 @@ int parse_nsec(const char *t, nsec_t *nsec);
bool ntp_synced(void);
int get_timezones(char ***l);
-bool timezone_is_valid(const char *name);
+bool timezone_is_valid(const char *name, int log_level);
bool clock_boottime_supported(void);
bool clock_supported(clockid_t clock);
@@ -196,5 +177,7 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
/* With a 32bit time_t we can't go beyond 2038... */
#define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 2147483647000000)
#else
-#error "Yuck, time_t is neither 4 not 8 bytes wide?"
+#error "Yuck, time_t is neither 4 nor 8 bytes wide?"
#endif
+
+int time_change_fd(void);
diff --git a/src/basic/umask-util.h b/src/basic/umask-util.h
index 638b37d7de..e964292eaf 100644
--- a/src/basic/umask-util.h
+++ b/src/basic/umask-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/types.h>
diff --git a/src/basic/unaligned.h b/src/basic/unaligned.h
index 73302b4239..8a1d06445e 100644
--- a/src/basic/unaligned.h
+++ b/src/basic/unaligned.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <endian.h>
#include <stdint.h>
diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c
index 387533f597..ac6a9b37e8 100644
--- a/src/basic/unit-def.c
+++ b/src/basic/unit-def.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-label.h"
@@ -106,6 +88,7 @@ static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
[UNIT_STUB] = "stub",
[UNIT_LOADED] = "loaded",
[UNIT_NOT_FOUND] = "not-found",
+ [UNIT_BAD_SETTING] = "bad-setting",
[UNIT_ERROR] = "error",
[UNIT_MERGED] = "merged",
[UNIT_MASKED] = "masked"
diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h
index c142e069a6..d7e2d74669 100644
--- a/src/basic/unit-def.h
+++ b/src/basic/unit-def.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "macro.h"
@@ -43,8 +24,9 @@ typedef enum UnitType {
typedef enum UnitLoadState {
UNIT_STUB = 0,
UNIT_LOADED,
- UNIT_NOT_FOUND,
- UNIT_ERROR,
+ UNIT_NOT_FOUND, /* error condition #1: unit file not found */
+ UNIT_BAD_SETTING, /* error condition #2: we couldn't parse some essential unit file setting */
+ UNIT_ERROR, /* error condition #3: other "system" error, catchall for the rest */
UNIT_MERGED,
UNIT_MASKED,
_UNIT_LOAD_STATE_MAX,
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index 0fa0472ee1..1b81fe268f 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stddef.h>
@@ -254,25 +236,43 @@ int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
}
int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret) {
- char *s;
+ UnitType type;
assert(prefix);
assert(suffix);
assert(ret);
+ if (suffix[0] != '.')
+ return -EINVAL;
+
+ type = unit_type_from_string(suffix + 1);
+ if (type < 0)
+ return -EINVAL;
+
+ return unit_name_build_from_type(prefix, instance, type, ret);
+}
+
+int unit_name_build_from_type(const char *prefix, const char *instance, UnitType type, char **ret) {
+ const char *ut;
+ char *s;
+
+ assert(prefix);
+ assert(type >= 0);
+ assert(type < _UNIT_TYPE_MAX);
+ assert(ret);
+
if (!unit_prefix_is_valid(prefix))
return -EINVAL;
if (instance && !unit_instance_is_valid(instance))
return -EINVAL;
- if (!unit_suffix_is_valid(suffix))
- return -EINVAL;
+ ut = unit_type_to_string(type);
if (!instance)
- s = strappend(prefix, suffix);
+ s = strjoin(prefix, ".", ut);
else
- s = strjoin(prefix, "@", instance, suffix);
+ s = strjoin(prefix, "@", instance, ".", ut);
if (!s)
return -ENOMEM;
@@ -363,8 +363,7 @@ int unit_name_unescape(const char *f, char **ret) {
*t = 0;
- *ret = r;
- r = NULL;
+ *ret = TAKE_PTR(r);
return 0;
}
@@ -379,9 +378,9 @@ int unit_name_path_escape(const char *f, char **ret) {
if (!p)
return -ENOMEM;
- path_kill_slashes(p);
+ path_simplify(p, false);
- if (STR_IN_SET(p, "/", ""))
+ if (empty_or_root(p))
s = strdup("-");
else {
if (!path_is_normalized(p))
@@ -569,28 +568,32 @@ int unit_name_to_path(const char *name, char **ret) {
return unit_name_path_unescape(prefix, ret);
}
-static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t) {
+static bool do_escape_mangle(const char *f, bool allow_globs, char *t) {
const char *valid_chars;
+ bool mangled = false;
assert(f);
- assert(IN_SET(allow_globs, UNIT_NAME_GLOB, UNIT_NAME_NOGLOB));
assert(t);
- /* We'll only escape the obvious characters here, to play
- * safe. */
+ /* We'll only escape the obvious characters here, to play safe.
+ *
+ * Returns true if any characters were mangled, false otherwise.
+ */
- valid_chars = allow_globs == UNIT_NAME_GLOB ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT;
+ valid_chars = allow_globs ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT;
- for (; *f; f++) {
- if (*f == '/')
+ for (; *f; f++)
+ if (*f == '/') {
*(t++) = '-';
- else if (!strchr(valid_chars, *f))
+ mangled = true;
+ } else if (!strchr(valid_chars, *f)) {
t = do_escape_char(*f, t);
- else
+ mangled = true;
+ } else
*(t++) = *f;
- }
+ *t = 0;
- return t;
+ return mangled;
}
/**
@@ -600,9 +603,10 @@ static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t
*
* If @allow_globs, globs characters are preserved. Otherwise, they are escaped.
*/
-int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret) {
- char *s, *t;
+int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const char *suffix, char **ret) {
+ char *s;
int r;
+ bool mangled;
assert(name);
assert(suffix);
@@ -619,7 +623,7 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, c
goto good;
/* Already a fully valid globbing expression? If so, no mangling is necessary either... */
- if (allow_globs == UNIT_NAME_GLOB &&
+ if ((flags & UNIT_NAME_MANGLE_GLOB) &&
string_is_glob(name) &&
in_charset(name, VALID_CHARS_GLOB))
goto good;
@@ -644,13 +648,16 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, c
if (!s)
return -ENOMEM;
- t = do_escape_mangle(name, allow_globs, s);
- *t = 0;
+ mangled = do_escape_mangle(name, flags & UNIT_NAME_MANGLE_GLOB, s);
+ if (mangled)
+ log_full(flags & UNIT_NAME_MANGLE_WARN ? LOG_NOTICE : LOG_DEBUG,
+ "Invalid unit name \"%s\" was escaped as \"%s\" (maybe you should use systemd-escape?)",
+ name, s);
/* Append a suffix if it doesn't have any, but only if this is not a glob, so that we can allow "foo.*" as a
* valid glob. */
- if ((allow_globs != UNIT_NAME_GLOB || !string_is_glob(s)) && unit_name_to_type(s) < 0)
- strcpy(t, suffix);
+ if ((!(flags & UNIT_NAME_MANGLE_GLOB) || !string_is_glob(s)) && unit_name_to_type(s) < 0)
+ strcat(s, suffix);
*ret = s;
return 1;
@@ -698,7 +705,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
return 1;
}
-int slice_build_subslice(const char *slice, const char*name, char **ret) {
+int slice_build_subslice(const char *slice, const char *name, char **ret) {
char *subslice;
assert(slice);
diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h
index b47327dcaf..61abcd585b 100644
--- a/src/basic/unit-name.h
+++ b/src/basic/unit-name.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "macro.h"
@@ -53,6 +34,7 @@ UnitType unit_name_to_type(const char *n) _pure_;
int unit_name_change_suffix(const char *n, const char *suffix, char **ret);
int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret);
+int unit_name_build_from_type(const char *prefix, const char *instance, UnitType, char **ret);
char *unit_name_escape(const char *f);
int unit_name_unescape(const char *f, char **ret);
@@ -68,14 +50,14 @@ int unit_name_from_path_instance(const char *prefix, const char *path, const cha
int unit_name_to_path(const char *name, char **ret);
typedef enum UnitNameMangle {
- UNIT_NAME_NOGLOB,
- UNIT_NAME_GLOB,
+ UNIT_NAME_MANGLE_GLOB = 1,
+ UNIT_NAME_MANGLE_WARN = 2,
} UnitNameMangle;
-int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret);
+int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const char *suffix, char **ret);
-static inline int unit_name_mangle(const char *name, UnitNameMangle allow_globs, char **ret) {
- return unit_name_mangle_with_suffix(name, allow_globs, ".service", ret);
+static inline int unit_name_mangle(const char *name, UnitNameMangle flags, char **ret) {
+ return unit_name_mangle_with_suffix(name, flags, ".service", ret);
}
int slice_build_parent_slice(const char *slice, char **ret);
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index ceb71b61e8..a562a397c7 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <alloca.h>
#include <errno.h>
@@ -234,8 +216,7 @@ int get_user_creds_clean(
(isempty(*shell) || is_nologin_shell(*shell)))
*shell = NULL;
- if (home &&
- (isempty(*home) || path_equal(*home, "/")))
+ if (home && empty_or_root(*home))
*home = NULL;
return 0;
@@ -734,3 +715,111 @@ bool synthesize_nobody(void) {
return cache;
#endif
}
+
+int putpwent_sane(const struct passwd *pw, FILE *stream) {
+ assert(pw);
+ assert(stream);
+
+ errno = 0;
+ if (putpwent(pw, stream) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ return 0;
+}
+
+int putspent_sane(const struct spwd *sp, FILE *stream) {
+ assert(sp);
+ assert(stream);
+
+ errno = 0;
+ if (putspent(sp, stream) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ return 0;
+}
+
+int putgrent_sane(const struct group *gr, FILE *stream) {
+ assert(gr);
+ assert(stream);
+
+ errno = 0;
+ if (putgrent(gr, stream) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ return 0;
+}
+
+#if ENABLE_GSHADOW
+int putsgent_sane(const struct sgrp *sg, FILE *stream) {
+ assert(sg);
+ assert(stream);
+
+ errno = 0;
+ if (putsgent(sg, stream) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ return 0;
+}
+#endif
+
+int fgetpwent_sane(FILE *stream, struct passwd **pw) {
+ struct passwd *p;
+
+ assert(pw);
+ assert(stream);
+
+ errno = 0;
+ p = fgetpwent(stream);
+ if (!p && errno != ENOENT)
+ return errno > 0 ? -errno : -EIO;
+
+ *pw = p;
+ return !!p;
+}
+
+int fgetspent_sane(FILE *stream, struct spwd **sp) {
+ struct spwd *s;
+
+ assert(sp);
+ assert(stream);
+
+ errno = 0;
+ s = fgetspent(stream);
+ if (!s && errno != ENOENT)
+ return errno > 0 ? -errno : -EIO;
+
+ *sp = s;
+ return !!s;
+}
+
+int fgetgrent_sane(FILE *stream, struct group **gr) {
+ struct group *g;
+
+ assert(gr);
+ assert(stream);
+
+ errno = 0;
+ g = fgetgrent(stream);
+ if (!g && errno != ENOENT)
+ return errno > 0 ? -errno : -EIO;
+
+ *gr = g;
+ return !!g;
+}
+
+#if ENABLE_GSHADOW
+int fgetsgent_sane(FILE *stream, struct sgrp **sg) {
+ struct sgrp *s;
+
+ assert(sg);
+ assert(stream);
+
+ errno = 0;
+ s = fgetsgent(stream);
+ if (!s && errno != ENOENT)
+ return errno > 0 ? -errno : -EIO;
+
+ *sg = s;
+ return !!s;
+}
+#endif
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
index e1259a1582..b74f168859 100644
--- a/src/basic/user-util.h
+++ b/src/basic/user-util.h
@@ -1,25 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
+#include <grp.h>
+#include <gshadow.h>
+#include <pwd.h>
+#include <shadow.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
@@ -110,3 +95,14 @@ static inline bool valid_shell(const char *p) {
int maybe_setgroups(size_t size, const gid_t *list);
bool synthesize_nobody(void);
+
+int fgetpwent_sane(FILE *stream, struct passwd **pw);
+int fgetspent_sane(FILE *stream, struct spwd **sp);
+int fgetgrent_sane(FILE *stream, struct group **gr);
+int putpwent_sane(const struct passwd *pw, FILE *stream);
+int putspent_sane(const struct spwd *sp, FILE *stream);
+int putgrent_sane(const struct group *gr, FILE *stream);
+#ifdef ENABLE_GSHADOW
+int fgetsgent_sane(FILE *stream, struct sgrp **sg);
+int putsgent_sane(const struct sgrp *sg, FILE *stream);
+#endif
diff --git a/src/basic/utf8.c b/src/basic/utf8.c
index b17f420264..a5ce1a2944 100644
--- a/src/basic/utf8.c
+++ b/src/basic/utf8.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2011 Kay Sievers
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
/* Parts of this file are based on the GLIB utf8 validation functions. The
* original license text follows. */
@@ -48,6 +29,7 @@
#include <string.h>
#include "alloc-util.h"
+#include "gunicode.h"
#include "hexdecoct.h"
#include "macro.h"
#include "utf8.h"
@@ -259,6 +241,9 @@ char *utf8_escape_non_printable(const char *str) {
char *ascii_is_valid(const char *str) {
const char *p;
+ /* Check whether the string consists of valid ASCII bytes,
+ * i.e values between 0 and 127, inclusive. */
+
assert(str);
for (p = str; *p; p++)
@@ -268,6 +253,21 @@ char *ascii_is_valid(const char *str) {
return (char*) str;
}
+char *ascii_is_valid_n(const char *str, size_t len) {
+ size_t i;
+
+ /* Very similar to ascii_is_valid(), but checks exactly len
+ * bytes and rejects any NULs in that range. */
+
+ assert(str);
+
+ for (i = 0; i < len; i++)
+ if ((unsigned char) str[i] >= 128 || str[i] == 0)
+ return NULL;
+
+ return (char*) str;
+}
+
/**
* utf8_encode_unichar() - Encode single UCS-4 character as UTF-8
* @out_utf8: output buffer of at least 4 bytes or NULL
@@ -427,3 +427,23 @@ size_t utf8_n_codepoints(const char *str) {
return n;
}
+
+size_t utf8_console_width(const char *str) {
+ size_t n = 0;
+
+ /* Returns the approximate width a string will take on screen when printed on a character cell
+ * terminal/console. */
+
+ while (*str != 0) {
+ char32_t c;
+
+ if (utf8_encoded_to_unichar(str, &c) < 0)
+ return (size_t) -1;
+
+ str = utf8_next_char(str);
+
+ n += unichar_iswide(c) ? 2 : 1;
+ }
+
+ return n;
+}
diff --git a/src/basic/utf8.h b/src/basic/utf8.h
index 7128615181..e8af7a576b 100644
--- a/src/basic/utf8.h
+++ b/src/basic/utf8.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -35,6 +16,7 @@ bool unichar_is_valid(char32_t c);
const char *utf8_is_valid(const char *s) _pure_;
char *ascii_is_valid(const char *s) _pure_;
+char *ascii_is_valid_n(const char *str, size_t len);
bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_;
#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)
@@ -61,3 +43,4 @@ static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t t
}
size_t utf8_n_codepoints(const char *str);
+size_t utf8_console_width(const char *str);
diff --git a/src/basic/util.c b/src/basic/util.c
index 7863a14fb2..8f2d6061da 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <alloca.h>
#include <errno.h>
@@ -181,11 +163,13 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
const void *p;
int comparison;
+ assert(!size_multiply_overflow(nmemb, size));
+
l = 0;
u = nmemb;
while (l < u) {
idx = (l + u) / 2;
- p = (const char *) base + idx * size;
+ p = (const uint8_t*) base + idx * size;
comparison = compar(key, p, arg);
if (comparison < 0)
u = idx;
@@ -275,7 +259,7 @@ int container_get_leader(const char *machine, pid_t *pid) {
return -EINVAL;
p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
if (r == -ENOENT)
return -EHOSTDOWN;
if (r < 0)
@@ -416,6 +400,7 @@ uint64_t physical_memory(void) {
uint64_t mem, lim;
size_t ps;
long sc;
+ int r;
/* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
* memory.
@@ -429,13 +414,40 @@ uint64_t physical_memory(void) {
ps = page_size();
mem = (uint64_t) sc * (uint64_t) ps;
- if (cg_get_root_path(&root) < 0)
+ r = cg_get_root_path(&root);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
return mem;
+ }
- if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
+ r = cg_all_unified();
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
return mem;
+ }
+ if (r > 0) {
+ r = cg_get_attribute("memory", root, "memory.max", &value);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
+ return mem;
+ }
- if (safe_atou64(value, &lim) < 0)
+ if (streq(value, "max"))
+ return mem;
+ } else {
+ r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
+ return mem;
+ }
+ }
+
+ r = safe_atou64(value, &lim);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
+ return mem;
+ }
+ if (lim == UINT64_MAX)
return mem;
/* Make sure the limit is a multiple of our own page size */
@@ -476,6 +488,7 @@ uint64_t system_tasks_max(void) {
uint64_t a = TASKS_MAX, b = TASKS_MAX;
_cleanup_free_ char *root = NULL;
+ int r;
/* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
* limit:
@@ -486,13 +499,24 @@ uint64_t system_tasks_max(void) {
*
* And then pick the smallest of the three */
- (void) procfs_tasks_get_limit(&a);
+ r = procfs_tasks_get_limit(&a);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m");
- if (cg_get_root_path(&root) >= 0) {
+ r = cg_get_root_path(&root);
+ if (r < 0)
+ log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
+ else {
_cleanup_free_ char *value = NULL;
- if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
- (void) safe_atou64(value, &b);
+ r = cg_get_attribute("pids", root, "pids.max", &value);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m");
+ else if (!streq(value, "max")) {
+ r = safe_atou64(value, &b);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m");
+ }
}
return MIN3(TASKS_MAX,
diff --git a/src/basic/util.h b/src/basic/util.h
index 6f8d8bef34..9699d228f9 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <errno.h>
#include <fcntl.h>
@@ -92,6 +73,19 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
void *arg);
/**
+ * Normal bsearch requires base to be nonnull. Here were require
+ * that only if nmemb > 0.
+ */
+static inline void* bsearch_safe(const void *key, const void *base,
+ size_t nmemb, size_t size, comparison_fn_t compar) {
+ if (nmemb <= 0)
+ return NULL;
+
+ assert(base);
+ return bsearch(key, base, nmemb, size, compar);
+}
+
+/**
* Normal qsort requires base to be nonnull. Here were require
* that only if nmemb > 0.
*/
@@ -103,6 +97,22 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_
qsort(base, nmemb, size, compar);
}
+/* A wrapper around the above, but that adds typesafety: the element size is automatically derived from the type and so
+ * is the prototype for the comparison function */
+#define typesafe_qsort(p, n, func) \
+ ({ \
+ int (*_func_)(const typeof(p[0])*, const typeof(p[0])*) = func; \
+ qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \
+ })
+
+static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void *userdata) {
+ if (nmemb <= 1)
+ return;
+
+ assert(base);
+ qsort_r(base, nmemb, size, compar, userdata);
+}
+
/**
* Normal memcpy requires src to be nonnull. We do nothing if n is 0.
*/
diff --git a/src/basic/verbs.c b/src/basic/verbs.c
index 4f3cd91465..1893ea3733 100644
--- a/src/basic/verbs.c
+++ b/src/basic/verbs.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
@@ -94,7 +76,7 @@ int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
if (name)
found = streq(name, verbs[i].verb);
else
- found = !!(verbs[i].flags & VERB_DEFAULT);
+ found = verbs[i].flags & VERB_DEFAULT;
if (found) {
verb = &verbs[i];
diff --git a/src/basic/verbs.h b/src/basic/verbs.h
index d9259fc45f..e174255a76 100644
--- a/src/basic/verbs.h
+++ b/src/basic/verbs.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#define VERB_ANY ((unsigned) -1)
typedef enum VerbFlags {
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 971701acca..d347732bb3 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#if defined(__i386__) || defined(__x86_64__)
#include <cpuid.h>
@@ -69,7 +51,7 @@ static int detect_vm_cpuid(void) {
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0)
return VIRTUALIZATION_NONE;
- hypervisor = !!(ecx & 0x80000000U);
+ hypervisor = ecx & 0x80000000U;
if (hypervisor) {
union {
@@ -324,8 +306,8 @@ static int detect_vm_zvm(void) {
/* Returns a short identifier for the various VM implementations */
int detect_vm(void) {
static thread_local int cached_found = _VIRTUALIZATION_INVALID;
- int r, dmi;
bool other = false;
+ int r, dmi;
if (cached_found >= 0)
return cached_found;
@@ -349,68 +331,58 @@ int detect_vm(void) {
r = detect_vm_cpuid();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE) {
- if (r == VIRTUALIZATION_VM_OTHER)
- other = true;
- else
- goto finish;
- }
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
+ goto finish;
- r = dmi;
- if (r < 0)
- return r;
- if (r != VIRTUALIZATION_NONE) {
- if (r == VIRTUALIZATION_VM_OTHER)
- other = true;
- else
- goto finish;
+ /* Now, let's get back to DMI */
+ if (dmi < 0)
+ return dmi;
+ if (dmi == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (dmi != VIRTUALIZATION_NONE) {
+ r = dmi;
+ goto finish;
}
/* x86 xen will most likely be detected by cpuid. If not (most likely
* because we're not an x86 guest), then we should try the /proc/xen
* directory next. If that's not found, then we check for the high-level
* hypervisor sysfs file.
- */
+ */
r = detect_vm_xen();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE) {
- if (r == VIRTUALIZATION_VM_OTHER)
- other = true;
- else
- goto finish;
- }
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
+ goto finish;
r = detect_vm_hypervisor();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE) {
- if (r == VIRTUALIZATION_VM_OTHER)
- other = true;
- else
- goto finish;
- }
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
+ goto finish;
r = detect_vm_device_tree();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE) {
- if (r == VIRTUALIZATION_VM_OTHER)
- other = true;
- else
- goto finish;
- }
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
+ goto finish;
r = detect_vm_uml();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE) {
- if (r == VIRTUALIZATION_VM_OTHER)
- other = true;
- else
- goto finish;
- }
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
+ goto finish;
r = detect_vm_zvm();
if (r < 0)
@@ -421,10 +393,12 @@ finish:
* In order to detect the Dom0 as not virtualization we need to
* double-check it */
if (r == VIRTUALIZATION_XEN) {
- int ret = detect_vm_xen_dom0();
- if (ret < 0)
- return ret;
- if (ret > 0)
+ int dom0;
+
+ dom0 = detect_vm_xen_dom0();
+ if (dom0 < 0)
+ return dom0;
+ if (dom0 > 0)
r = VIRTUALIZATION_NONE;
} else if (r == VIRTUALIZATION_NONE && other)
r = VIRTUALIZATION_VM_OTHER;
diff --git a/src/basic/virt.h b/src/basic/virt.h
index 1216bc7456..c4cf4bfeab 100644
--- a/src/basic/virt.h
+++ b/src/basic/virt.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "macro.h"
diff --git a/src/basic/web-util.c b/src/basic/web-util.c
index d721b02653..82221af194 100644
--- a/src/basic/web-util.c
+++ b/src/basic/web-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
diff --git a/src/basic/web-util.h b/src/basic/web-util.h
index ad8c850d1d..c9e67e5c0a 100644
--- a/src/basic/web-util.h
+++ b/src/basic/web-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "macro.h"
diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c
index a37ee4b7ef..c5c55ea846 100644
--- a/src/basic/xattr-util.c
+++ b/src/basic/xattr-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/basic/xattr-util.h b/src/basic/xattr-util.h
index e25970ee6d..9fa85d7129 100644
--- a/src/basic/xattr-util.h
+++ b/src/basic/xattr-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
diff --git a/src/basic/xml.c b/src/basic/xml.c
index 639c3438a0..cb34d870c1 100644
--- a/src/basic/xml.c
+++ b/src/basic/xml.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stddef.h>
diff --git a/src/basic/xml.h b/src/basic/xml.h
index d00b527232..8da2ff5f75 100644
--- a/src/basic/xml.h
+++ b/src/basic/xml.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
enum {
XML_END,
XML_TEXT,
diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c
index eb888e88ea..697e16c53a 100644
--- a/src/binfmt/binfmt.c
+++ b/src/binfmt/binfmt.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
@@ -32,11 +14,14 @@
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
+#include "pager.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
#include "util.h"
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d");
+static bool arg_cat_config = false;
+static bool arg_no_pager = false;
static int delete_rule(const char *rule) {
_cleanup_free_ char *x = NULL, *fn = NULL;
@@ -76,7 +61,7 @@ static int apply_file(const char *path, bool ignore_enoent) {
assert(path);
- r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
+ r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f);
if (r < 0) {
if (ignore_enoent && r == -ENOENT)
return 0;
@@ -115,6 +100,8 @@ static void help(void) {
"Registers binary formats.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --cat-config Show configuration files\n"
+ " --no-pager Do not pipe output into a pager\n"
, program_invocation_short_name);
}
@@ -122,11 +109,15 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
+ ARG_CAT_CONFIG,
+ ARG_NO_PAGER,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
@@ -146,6 +137,14 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_VERSION:
return version();
+ case ARG_CAT_CONFIG:
+ arg_cat_config = true;
+ break;
+
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
case '?':
return -EINVAL;
@@ -153,6 +152,11 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached("Unhandled option");
}
+ if (arg_cat_config && argc > optind) {
+ log_error("Positional arguments are not allowed with --cat-config");
+ return -EINVAL;
+ }
+
return 1;
}
@@ -183,12 +187,19 @@ int main(int argc, char *argv[]) {
_cleanup_strv_free_ char **files = NULL;
char **f;
- r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
+ r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d"));
if (r < 0) {
log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
goto finish;
}
+ if (arg_cat_config) {
+ (void) pager_open(arg_no_pager, false);
+
+ r = cat_files(NULL, files, 0);
+ goto finish;
+ }
+
/* Flush out all rules */
write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
@@ -200,5 +211,7 @@ int main(int argc, char *argv[]) {
}
finish:
+ pager_close();
+
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index fe72a7d46e..534870ee50 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013-2015 Kay Sievers
- 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 <blkid.h>
#include <ctype.h>
@@ -441,8 +422,7 @@ static int copy_file_with_version_check(const char *from, const char *to, bool f
(void) fsync_directory_of_file(fd_to);
- r = renameat(AT_FDCWD, t, AT_FDCWD, to);
- if (r < 0) {
+ if (renameat(AT_FDCWD, t, AT_FDCWD, to) < 0) {
(void) unlink_noerrno(t);
return log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", t, to);
}
@@ -827,6 +807,7 @@ static int install_loader_config(const char *esp_path) {
}
fprintf(f, "#timeout 3\n");
+ fprintf(f, "#console-mode keep\n");
fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
r = fflush_sync_and_check(f);
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 06331da2d4..2f014446be 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -1,17 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2015 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012-2015 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2012-2015 Harald Hoyer <harald@redhat.com>
*/
#include <efi.h>
@@ -68,7 +57,11 @@ typedef struct {
CHAR16 *entry_default_pattern;
CHAR16 *entry_oneshot;
CHAR16 *options_edit;
- BOOLEAN no_editor;
+ BOOLEAN editor;
+ BOOLEAN auto_entries;
+ BOOLEAN auto_firmware;
+ UINTN console_mode;
+ enum console_mode_change_type console_mode_change;
} Config;
static VOID cursor_left(UINTN *cursor, UINTN *first) {
@@ -86,15 +79,9 @@ static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len) {
}
static BOOLEAN line_edit(CHAR16 *line_in, CHAR16 **line_out, UINTN x_max, UINTN y_pos) {
- CHAR16 *line;
- UINTN size;
- UINTN len;
- UINTN first;
- CHAR16 *print;
- UINTN cursor;
- UINTN clear;
- BOOLEAN exit;
- BOOLEAN enter;
+ _cleanup_freepool_ CHAR16 *line = NULL, *print = NULL;
+ UINTN size, len, first, cursor, clear;
+ BOOLEAN exit, enter;
if (!line_in)
line_in = L"";
@@ -322,8 +309,6 @@ static BOOLEAN line_edit(CHAR16 *line_in, CHAR16 **line_out, UINTN x_max, UINTN
}
uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE);
- FreePool(print);
- FreePool(line);
return enter;
}
@@ -356,11 +341,9 @@ static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) {
static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
UINT64 key;
UINTN i;
- CHAR16 *s;
- CHAR8 *b;
- UINTN x;
- UINTN y;
- UINTN size;
+ _cleanup_freepool_ CHAR8 *bootvar = NULL, *modevar = NULL, *indvar = NULL;
+ _cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL;
+ UINTN x, y, size;
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@@ -375,24 +358,20 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
if (uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x, &y) == EFI_SUCCESS)
Print(L"console size: %d x %d\n", x, y);
- if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
- Print(L"SecureBoot: %s\n", yes_no(*b > 0));
- FreePool(b);
- }
+ if (efivar_get_raw(&global_guid, L"SecureBoot", &bootvar, &size) == EFI_SUCCESS)
+ Print(L"SecureBoot: %s\n", yes_no(*bootvar > 0));
- if (efivar_get_raw(&global_guid, L"SetupMode", &b, &size) == EFI_SUCCESS) {
- Print(L"SetupMode: %s\n", *b > 0 ? L"setup" : L"user");
- FreePool(b);
- }
+ if (efivar_get_raw(&global_guid, L"SetupMode", &modevar, &size) == EFI_SUCCESS)
+ Print(L"SetupMode: %s\n", *modevar > 0 ? L"setup" : L"user");
if (shim_loaded())
Print(L"Shim: present\n");
- if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
- Print(L"OsIndicationsSupported: %d\n", (UINT64)*b);
- FreePool(b);
- }
- Print(L"\n");
+ if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &indvar, &size) == EFI_SUCCESS)
+ Print(L"OsIndicationsSupported: %d\n", (UINT64)*indvar);
+
+ Print(L"\n--- press key ---\n\n");
+ console_key_read(&key, TRUE);
Print(L"timeout: %d\n", config->timeout_sec);
if (config->timeout_sec_efivar >= 0)
@@ -400,7 +379,9 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"timeout (config): %d\n", config->timeout_sec_config);
if (config->entry_default_pattern)
Print(L"default pattern: '%s'\n", config->entry_default_pattern);
- Print(L"editor: %s\n", yes_no(!config->no_editor));
+ Print(L"editor: %s\n", yes_no(config->editor));
+ Print(L"auto-entries: %s\n", yes_no(config->auto_entries));
+ Print(L"auto-firmware: %s\n", yes_no(config->auto_firmware));
Print(L"\n");
Print(L"config entry count: %d\n", config->entry_count);
@@ -413,14 +394,10 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"LoaderConfigTimeout: %d\n", i);
if (config->entry_oneshot)
Print(L"LoaderEntryOneShot: %s\n", config->entry_oneshot);
- if (efivar_get(L"LoaderDevicePartUUID", &s) == EFI_SUCCESS) {
- Print(L"LoaderDevicePartUUID: %s\n", s);
- FreePool(s);
- }
- if (efivar_get(L"LoaderEntryDefault", &s) == EFI_SUCCESS) {
- Print(L"LoaderEntryDefault: %s\n", s);
- FreePool(s);
- }
+ if (efivar_get(L"LoaderDevicePartUUID", &partstr) == EFI_SUCCESS)
+ Print(L"LoaderDevicePartUUID: %s\n", partstr);
+ if (efivar_get(L"LoaderEntryDefault", &defaultstr) == EFI_SUCCESS)
+ Print(L"LoaderEntryDefault: %s\n", defaultstr);
Print(L"\n--- press key ---\n\n");
console_key_read(&key, TRUE);
@@ -444,13 +421,13 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"machine-id '%s'\n", entry->machine_id);
if (entry->device) {
EFI_DEVICE_PATH *device_path;
- CHAR16 *str;
device_path = DevicePathFromHandle(entry->device);
if (device_path) {
+ _cleanup_freepool_ CHAR16 *str;
+
str = DevicePathToStr(device_path);
Print(L"device handle '%s'\n", str);
- FreePool(str);
}
}
if (entry->loader)
@@ -491,6 +468,7 @@ static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry, CHAR16 *load
BOOLEAN exit = FALSE;
BOOLEAN run = TRUE;
BOOLEAN wait = FALSE;
+ BOOLEAN cleared_screen = FALSE;
graphics_mode(FALSE);
uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE);
@@ -499,7 +477,18 @@ static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry, CHAR16 *load
/* draw a single character to make ClearScreen work on some firmware */
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L" ");
- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+
+ if (config->console_mode_change != CONSOLE_MODE_KEEP) {
+ err = console_set_mode(&config->console_mode, config->console_mode_change);
+ if (!EFI_ERROR(err))
+ cleared_screen = TRUE;
+ }
+
+ if (!cleared_screen)
+ uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+
+ if (config->console_mode_change != CONSOLE_MODE_KEEP && EFI_ERROR(err))
+ Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err);
err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max);
if (EFI_ERROR(err)) {
@@ -774,7 +763,7 @@ static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry, CHAR16 *load
case KEYPRESS(0, 0, 'e'):
/* only the options of configured entries can be edited */
- if (config->no_editor || config->entries[idx_highlight]->type == LOADER_UNDEFINED)
+ if (!config->editor || config->entries[idx_highlight]->type == LOADER_UNDEFINED)
break;
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1);
@@ -985,12 +974,11 @@ static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) {
line = content;
while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) {
if (strcmpa((CHAR8 *)"timeout", key) == 0) {
- CHAR16 *s;
+ _cleanup_freepool_ CHAR16 *s = NULL;
s = stra_to_str(value);
config->timeout_sec_config = Atoi(s);
config->timeout_sec = config->timeout_sec_config;
- FreePool(s);
continue;
}
@@ -1006,7 +994,41 @@ static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) {
if (EFI_ERROR(parse_boolean(value, &on)))
continue;
- config->no_editor = !on;
+ config->editor = on;
+ }
+
+ if (strcmpa((CHAR8 *)"auto-entries", key) == 0) {
+ BOOLEAN on;
+
+ if (EFI_ERROR(parse_boolean(value, &on)))
+ continue;
+ config->auto_entries = on;
+ }
+
+ if (strcmpa((CHAR8 *)"auto-firmware", key) == 0) {
+ BOOLEAN on;
+
+ if (EFI_ERROR(parse_boolean(value, &on)))
+ continue;
+ config->auto_firmware = on;
+ }
+
+ if (strcmpa((CHAR8 *)"console-mode", key) == 0) {
+ if (strcmpa((CHAR8 *)"auto", value) == 0)
+ config->console_mode_change = CONSOLE_MODE_AUTO;
+ else if (strcmpa((CHAR8 *)"max", value) == 0)
+ config->console_mode_change = CONSOLE_MODE_MAX;
+ else if (strcmpa((CHAR8 *)"keep", value) == 0)
+ config->console_mode_change = CONSOLE_MODE_KEEP;
+ else {
+ _cleanup_freepool_ CHAR16 *s = NULL;
+
+ s = stra_to_str(value);
+ config->console_mode = Atoi(s);
+ config->console_mode_change = CONSOLE_MODE_SET;
+ }
+
+ continue;
}
}
}
@@ -1017,7 +1039,7 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
UINTN pos = 0;
CHAR8 *key, *value;
UINTN len;
- CHAR16 *initrd = NULL;
+ _cleanup_freepool_ CHAR16 *initrd = NULL;
entry = AllocateZeroPool(sizeof(ConfigEntry));
@@ -1072,7 +1094,7 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
}
if (strcmpa((CHAR8 *)"initrd", key) == 0) {
- CHAR16 *new;
+ _cleanup_freepool_ CHAR16 *new = NULL;
new = stra_to_path(value);
if (initrd) {
@@ -1083,12 +1105,12 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
initrd = s;
} else
initrd = PoolPrint(L"initrd=%s", new);
- FreePool(new);
+
continue;
}
if (strcmpa((CHAR8 *)"options", key) == 0) {
- CHAR16 *new;
+ _cleanup_freepool_ CHAR16 *new = NULL;
new = stra_to_str(value);
if (entry->options) {
@@ -1101,14 +1123,13 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
entry->options = new;
new = NULL;
}
- FreePool(new);
+
continue;
}
}
if (entry->type == LOADER_UNDEFINED) {
config_entry_free(entry);
- FreePool(initrd);
FreePool(entry);
return;
}
@@ -1126,7 +1147,6 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
initrd = NULL;
}
}
- FreePool(initrd);
entry->device = device;
entry->file = StrDuplicate(file);
@@ -1140,15 +1160,17 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
}
static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) {
- CHAR8 *content = NULL;
+ _cleanup_freepool_ CHAR8 *content = NULL;
UINTN sec;
- UINTN len;
EFI_STATUS err;
- len = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content);
- if (len > 0)
+ config->editor = TRUE;
+ config->auto_entries = TRUE;
+ config->auto_firmware = TRUE;
+
+ err = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content, NULL);
+ if (!EFI_ERROR(err))
config_defaults_load_from_file(config, content);
- FreePool(content);
err = efivar_get_int(L"LoaderConfigTimeout", &sec);
if (!EFI_ERROR(err)) {
@@ -1168,7 +1190,7 @@ static VOID config_load_entries(Config *config, EFI_HANDLE *device, EFI_FILE *ro
CHAR16 buf[256];
UINTN bufsize;
EFI_FILE_INFO *f;
- CHAR8 *content = NULL;
+ _cleanup_freepool_ CHAR8 *content = NULL;
UINTN len;
bufsize = sizeof(buf);
@@ -1190,10 +1212,9 @@ static VOID config_load_entries(Config *config, EFI_HANDLE *device, EFI_FILE *ro
if (StrnCmp(f->FileName, L"auto-", 5) == 0)
continue;
- len = file_read(entries_dir, f->FileName, 0, 0, &content);
- if (len > 0)
+ err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL);
+ if (!EFI_ERROR(err))
config_entry_add_from_file(config, device, f->FileName, content, loaded_image_path);
- FreePool(content);
}
uefi_call_wrapper(entries_dir->Close, 1, entries_dir);
}
@@ -1223,7 +1244,7 @@ static VOID config_sort_entries(Config *config) {
}
static VOID config_default_entry_select(Config *config) {
- CHAR16 *var;
+ _cleanup_freepool_ CHAR16 *entry_oneshot = NULL, *entry_default = NULL;
EFI_STATUS err;
UINTN i;
@@ -1231,21 +1252,19 @@ static VOID config_default_entry_select(Config *config) {
* The EFI variable to specify a boot entry for the next, and only the
* next reboot. The variable is always cleared directly after it is read.
*/
- err = efivar_get(L"LoaderEntryOneShot", &var);
+ err = efivar_get(L"LoaderEntryOneShot", &entry_oneshot);
if (!EFI_ERROR(err)) {
BOOLEAN found = FALSE;
- for (i = 0; i < config->entry_count; i++) {
- if (StrCmp(config->entries[i]->file, var) == 0) {
+ for (i = 0; i < config->entry_count; i++)
+ if (StrCmp(config->entries[i]->file, entry_oneshot) == 0) {
config->idx_default = i;
found = TRUE;
break;
}
- }
- config->entry_oneshot = StrDuplicate(var);
+ config->entry_oneshot = StrDuplicate(entry_oneshot);
efivar_set(L"LoaderEntryOneShot", NULL, TRUE);
- FreePool(var);
if (found)
return;
}
@@ -1256,21 +1275,14 @@ static VOID config_default_entry_select(Config *config) {
* the 'd' key in the loader selection menu, the entry is marked with
* an '*'.
*/
- err = efivar_get(L"LoaderEntryDefault", &var);
+ err = efivar_get(L"LoaderEntryDefault", &entry_default);
if (!EFI_ERROR(err)) {
- BOOLEAN found = FALSE;
-
- for (i = 0; i < config->entry_count; i++) {
- if (StrCmp(config->entries[i]->file, var) == 0) {
+ for (i = 0; i < config->entry_count; i++)
+ if (StrCmp(config->entries[i]->file, entry_default) == 0) {
config->idx_default = i;
config->idx_default_efivar = i;
- found = TRUE;
- break;
+ return;
}
- }
- FreePool(var);
- if (found)
- return;
}
config->idx_default_efivar = -1;
@@ -1364,7 +1376,7 @@ static VOID config_title_generate(Config *config) {
/* add machine-id to non-unique titles */
for (i = 0; i < config->entry_count; i++) {
CHAR16 *s;
- CHAR16 *m;
+ _cleanup_freepool_ CHAR16 *m = NULL;
if (!config->entries[i]->non_unique)
continue;
@@ -1376,7 +1388,6 @@ static VOID config_title_generate(Config *config) {
s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, m);
FreePool(config->entries[i]->title_show);
config->entries[i]->title_show = s;
- FreePool(m);
}
if (!find_nonunique(config->entries, config->entry_count))
@@ -1429,10 +1440,29 @@ static BOOLEAN config_entry_add_loader_auto(Config *config, EFI_HANDLE *device,
ConfigEntry *entry;
EFI_STATUS err;
- /* do not add an entry for ourselves */
- if (loaded_image_path && StriCmp(loader, loaded_image_path) == 0)
+ if (!config->auto_entries)
return FALSE;
+ /* do not add an entry for ourselves */
+ if (loaded_image_path) {
+ UINTN len;
+ _cleanup_freepool_ CHAR8 *content = NULL;
+
+ if (StriCmp(loader, loaded_image_path) == 0)
+ return FALSE;
+
+ /* look for systemd-boot magic string */
+ err = file_read(root_dir, loader, 0, 100*1024, &content, &len);
+ if (!EFI_ERROR(err)) {
+ CHAR8 *start = content;
+ CHAR8 *last = content + len - sizeof(magic) - 1;
+
+ for (; start <= last; start++)
+ if (start[0] == magic[0] && CompareMem(start, magic, sizeof(magic) - 1) == 0)
+ return FALSE;
+ }
+ }
+
/* check existence */
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, loader, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err))
@@ -1452,7 +1482,10 @@ static BOOLEAN config_entry_add_loader_auto(Config *config, EFI_HANDLE *device,
static VOID config_entry_add_osx(Config *config) {
EFI_STATUS err;
UINTN handle_count = 0;
- EFI_HANDLE *handles = NULL;
+ _cleanup_freepool_ EFI_HANDLE *handles = NULL;
+
+ if (!config->auto_entries)
+ return;
err = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &handle_count, &handles);
if (!EFI_ERROR(err)) {
@@ -1471,128 +1504,128 @@ static VOID config_entry_add_osx(Config *config) {
if (found)
break;
}
-
- FreePool(handles);
}
}
-static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_image, EFI_FILE *root_dir) {
+static VOID config_entry_add_linux(Config *config, EFI_LOADED_IMAGE *loaded_image, EFI_FILE *root_dir) {
EFI_FILE_HANDLE linux_dir;
EFI_STATUS err;
ConfigEntry *entry;
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL);
- if (!EFI_ERROR(err)) {
- for (;;) {
- CHAR16 buf[256];
- UINTN bufsize;
- EFI_FILE_INFO *f;
- CHAR8 *sections[] = {
- (UINT8 *)".osrel",
- (UINT8 *)".cmdline",
- NULL
- };
- UINTN offs[ELEMENTSOF(sections)-1] = {};
- UINTN szs[ELEMENTSOF(sections)-1] = {};
- UINTN addrs[ELEMENTSOF(sections)-1] = {};
- CHAR8 *content = NULL;
- UINTN len;
- CHAR8 *line;
- UINTN pos = 0;
- CHAR8 *key, *value;
- CHAR16 *os_name = NULL;
- CHAR16 *os_id = NULL;
- CHAR16 *os_version = NULL;
- CHAR16 *os_build = NULL;
-
- bufsize = sizeof(buf);
- err = uefi_call_wrapper(linux_dir->Read, 3, linux_dir, &bufsize, buf);
- if (bufsize == 0 || EFI_ERROR(err))
- break;
+ if (EFI_ERROR(err))
+ return;
- f = (EFI_FILE_INFO *) buf;
- if (f->FileName[0] == '.')
- continue;
- if (f->Attribute & EFI_FILE_DIRECTORY)
- continue;
- len = StrLen(f->FileName);
- if (len < 5)
- continue;
- if (StriCmp(f->FileName + len - 4, L".efi") != 0)
- continue;
+ for (;;) {
+ CHAR16 buf[256];
+ UINTN bufsize = sizeof buf;
+ EFI_FILE_INFO *f;
+ CHAR8 *sections[] = {
+ (UINT8 *)".osrel",
+ (UINT8 *)".cmdline",
+ NULL
+ };
+ UINTN offs[ELEMENTSOF(sections)-1] = {};
+ UINTN szs[ELEMENTSOF(sections)-1] = {};
+ UINTN addrs[ELEMENTSOF(sections)-1] = {};
+ CHAR8 *content = NULL;
+ UINTN len;
+ CHAR8 *line;
+ UINTN pos = 0;
+ CHAR8 *key, *value;
+ CHAR16 *os_name = NULL;
+ CHAR16 *os_id = NULL;
+ CHAR16 *os_version = NULL;
+ CHAR16 *os_build = NULL;
+
+ err = uefi_call_wrapper(linux_dir->Read, 3, linux_dir, &bufsize, buf);
+ if (bufsize == 0 || EFI_ERROR(err))
+ break;
- /* look for .osrel and .cmdline sections in the .efi binary */
- err = pe_file_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
- if (EFI_ERROR(err))
- continue;
+ f = (EFI_FILE_INFO *) buf;
+ if (f->FileName[0] == '.')
+ continue;
+ if (f->Attribute & EFI_FILE_DIRECTORY)
+ continue;
+ len = StrLen(f->FileName);
+ if (len < 5)
+ continue;
+ if (StriCmp(f->FileName + len - 4, L".efi") != 0)
+ continue;
- len = file_read(linux_dir, f->FileName, offs[0], szs[0], &content);
- if (len <= 0)
- continue;
+ /* look for .osrel and .cmdline sections in the .efi binary */
+ err = pe_file_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
+ if (EFI_ERROR(err))
+ continue;
- /* read properties from the embedded os-release file */
- line = content;
- while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) {
- if (strcmpa((CHAR8 *)"PRETTY_NAME", key) == 0) {
- FreePool(os_name);
- os_name = stra_to_str(value);
- continue;
- }
+ err = file_read(linux_dir, f->FileName, offs[0], szs[0], &content, NULL);
+ if (EFI_ERROR(err))
+ continue;
- if (strcmpa((CHAR8 *)"ID", key) == 0) {
- FreePool(os_id);
- os_id = stra_to_str(value);
- continue;
- }
+ /* read properties from the embedded os-release file */
+ line = content;
+ while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) {
+ if (strcmpa((CHAR8 *)"PRETTY_NAME", key) == 0) {
+ FreePool(os_name);
+ os_name = stra_to_str(value);
+ continue;
+ }
- if (strcmpa((CHAR8 *)"VERSION_ID", key) == 0) {
- FreePool(os_version);
- os_version = stra_to_str(value);
- continue;
- }
+ if (strcmpa((CHAR8 *)"ID", key) == 0) {
+ FreePool(os_id);
+ os_id = stra_to_str(value);
+ continue;
+ }
- if (strcmpa((CHAR8 *)"BUILD_ID", key) == 0) {
- FreePool(os_build);
- os_build = stra_to_str(value);
- continue;
- }
+ if (strcmpa((CHAR8 *)"VERSION_ID", key) == 0) {
+ FreePool(os_version);
+ os_version = stra_to_str(value);
+ continue;
}
- if (os_name && os_id && (os_version || os_build)) {
- CHAR16 *conf;
- CHAR16 *path;
- CHAR16 *cmdline;
-
- conf = PoolPrint(L"%s-%s", os_id, os_version ? : os_build);
- path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName);
- entry = config_entry_add_loader(config, loaded_image->DeviceHandle, LOADER_LINUX, conf, 'l', os_name, path);
-
- FreePool(content);
- /* read the embedded cmdline file */
- len = file_read(linux_dir, f->FileName, offs[1], szs[1] - 1 , &content);
- if (len > 0) {
- cmdline = stra_to_str(content);
- entry->options = cmdline;
- cmdline = NULL;
- }
- FreePool(cmdline);
- FreePool(conf);
- FreePool(path);
+ if (strcmpa((CHAR8 *)"BUILD_ID", key) == 0) {
+ FreePool(os_build);
+ os_build = stra_to_str(value);
+ continue;
}
+ }
+
+ if (os_name && os_id && (os_version || os_build)) {
+ CHAR16 *conf;
+ CHAR16 *path;
+ CHAR16 *cmdline;
+
+ conf = PoolPrint(L"%s-%s", os_id, os_version ? : os_build);
+ path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName);
+ entry = config_entry_add_loader(config, loaded_image->DeviceHandle, LOADER_LINUX, conf, 'l', os_name, path);
- FreePool(os_name);
- FreePool(os_id);
- FreePool(os_version);
- FreePool(os_build);
FreePool(content);
+ content = NULL;
+ /* read the embedded cmdline file */
+ err = file_read(linux_dir, f->FileName, offs[1], szs[1] - 1, &content, NULL);
+ if (!EFI_ERROR(err)) {
+ cmdline = stra_to_str(content);
+ entry->options = cmdline;
+ cmdline = NULL;
+ }
+ FreePool(cmdline);
+ FreePool(conf);
+ FreePool(path);
}
- uefi_call_wrapper(linux_dir->Close, 1, linux_dir);
+
+ FreePool(os_name);
+ FreePool(os_id);
+ FreePool(os_version);
+ FreePool(os_build);
+ FreePool(content);
}
+
+ uefi_call_wrapper(linux_dir->Close, 1, linux_dir);
}
static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, const ConfigEntry *entry) {
EFI_HANDLE image;
- EFI_DEVICE_PATH *path;
+ _cleanup_freepool_ EFI_DEVICE_PATH *path = NULL;
CHAR16 *options;
EFI_STATUS err;
@@ -1607,7 +1640,7 @@ static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, con
if (EFI_ERROR(err)) {
Print(L"Error loading %s: %r", entry->loader, err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- goto out;
+ return err;
}
if (config->options_edit)
@@ -1632,7 +1665,7 @@ static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, con
#if ENABLE_TPM
/* Try to log any options to the TPM, especially to catch manually edited options */
err = tpm_log_event(SD_TPM_PCR,
- (EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions,
+ (EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
if (EFI_ERROR(err)) {
Print(L"Unable to add image options measurement: %r", err);
@@ -1645,13 +1678,11 @@ static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, con
err = uefi_call_wrapper(BS->StartImage, 3, image, NULL, NULL);
out_unload:
uefi_call_wrapper(BS->UnloadImage, 1, image);
-out:
- FreePool(path);
return err;
}
static EFI_STATUS reboot_into_firmware(VOID) {
- CHAR8 *b;
+ _cleanup_freepool_ CHAR8 *b = NULL;
UINTN size;
UINT64 osind;
EFI_STATUS err;
@@ -1661,7 +1692,6 @@ static EFI_STATUS reboot_into_firmware(VOID) {
err = efivar_get_raw(&global_guid, L"OsIndications", &b, &size);
if (!EFI_ERROR(err))
osind |= (UINT64)*b;
- FreePool(b);
err = efivar_set_raw(&global_guid, L"OsIndications", (CHAR8 *)&osind, sizeof(UINT64), TRUE);
if (EFI_ERROR(err))
@@ -1685,7 +1715,7 @@ static VOID config_free(Config *config) {
}
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
- CHAR16 *s;
+ _cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL;
CHAR8 *b;
UINTN size;
EFI_LOADED_IMAGE *loaded_image;
@@ -1701,12 +1731,12 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
init_usec = time_usec();
efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec);
efivar_set(L"LoaderInfo", L"systemd-boot " PACKAGE_VERSION, FALSE);
- s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
- efivar_set(L"LoaderFirmwareInfo", s, FALSE);
- FreePool(s);
- s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
- efivar_set(L"LoaderFirmwareType", s, FALSE);
- FreePool(s);
+
+ infostr = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
+ efivar_set(L"LoaderFirmwareInfo", infostr, FALSE);
+
+ typestr = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
+ efivar_set(L"LoaderFirmwareType", typestr, FALSE);
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
@@ -1753,15 +1783,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
config_sort_entries(&config);
/* if we find some well-known loaders, add them to the end of the list */
- config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
+ config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, NULL,
L"auto-windows", 'w', L"Windows Boot Manager", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
- config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
+ config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, NULL,
L"auto-efi-shell", 's', L"EFI Shell", L"\\shell" EFI_MACHINE_TYPE_NAME ".efi");
config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
L"auto-efi-default", '\0', L"EFI Default Loader", L"\\EFI\\Boot\\boot" EFI_MACHINE_TYPE_NAME ".efi");
config_entry_add_osx(&config);
- if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
+ if (config.auto_firmware && efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
UINT64 osind = (UINT64)*b;
if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI)
diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c
index 4487ed099f..a365d08951 100644
--- a/src/boot/efi/console.c
+++ b/src/boot/efi/console.c
@@ -1,17 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2012 Harald Hoyer <harald@redhat.com>
*/
#include <efi.h>
@@ -20,6 +9,9 @@
#include "console.h"
#include "util.h"
+#define SYSTEM_FONT_WIDTH 8
+#define SYSTEM_FONT_HEIGHT 19
+
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
@@ -134,3 +126,105 @@ EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
*key = KEYPRESS(0, k.ScanCode, k.UnicodeChar);
return 0;
}
+
+static EFI_STATUS change_mode(UINTN mode) {
+ EFI_STATUS err;
+
+ err = uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, mode);
+
+ /* Special case mode 1: when using OVMF and qemu, setting it returns error
+ * and breaks console output. */
+ if (EFI_ERROR(err) && mode == 1)
+ uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, (UINTN)0);
+
+ return err;
+}
+
+static UINT64 text_area_from_font_size(void) {
+ EFI_STATUS err;
+ UINT64 text_area;
+ UINTN rows, columns;
+
+ err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &columns, &rows);
+ if (EFI_ERROR(err)) {
+ columns = 80;
+ rows = 25;
+ }
+
+ text_area = SYSTEM_FONT_WIDTH * SYSTEM_FONT_HEIGHT * (UINT64)rows * (UINT64)columns;
+
+ return text_area;
+}
+
+static EFI_STATUS mode_auto(UINTN *mode) {
+ const UINT32 HORIZONTAL_MAX_OK = 1920;
+ const UINT32 VERTICAL_MAX_OK = 1080;
+ const UINT64 VIEWPORT_RATIO = 10;
+ UINT64 screen_area, text_area;
+ EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ EFI_STATUS err;
+ BOOLEAN keep = FALSE;
+
+ err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
+ if (!EFI_ERROR(err) && GraphicsOutput->Mode && GraphicsOutput->Mode->Info) {
+ Info = GraphicsOutput->Mode->Info;
+
+ /* Start verifying if we are in a resolution larger than Full HD
+ * (1920x1080). If we're not, assume we're in a good mode and do not
+ * try to change it. */
+ if (Info->HorizontalResolution <= HORIZONTAL_MAX_OK && Info->VerticalResolution <= VERTICAL_MAX_OK)
+ keep = TRUE;
+ /* For larger resolutions, calculate the ratio of the total screen
+ * area to the text viewport area. If it's less than 10 times bigger,
+ * then assume the text is readable and keep the text mode. */
+ else {
+ screen_area = (UINT64)Info->HorizontalResolution * (UINT64)Info->VerticalResolution;
+ text_area = text_area_from_font_size();
+
+ if (text_area != 0 && screen_area/text_area < VIEWPORT_RATIO)
+ keep = TRUE;
+ }
+ }
+
+ if (keep) {
+ /* Just clear the screen instead of changing the mode and return. */
+ *mode = ST->ConOut->Mode->Mode;
+ uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+ return EFI_SUCCESS;
+ }
+
+ /* If we reached here, then we have a high resolution screen and the text
+ * viewport is less than 10% the screen area, so the firmware developer
+ * screwed up. Try to switch to a better mode. Mode number 2 is first non
+ * standard mode, which is provided by the device manufacturer, so it should
+ * be a good mode.
+ * Note: MaxMode is the number of modes, not the last mode. */
+ if (ST->ConOut->Mode->MaxMode > 2)
+ *mode = 2;
+ /* Try again with mode different than zero (assume user requests
+ * auto mode due to some problem with mode zero). */
+ else if (ST->ConOut->Mode->MaxMode == 2)
+ *mode = 1;
+ /* Else force mode change to zero. */
+ else
+ *mode = 0;
+
+ return change_mode(*mode);
+}
+
+EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how) {
+ if (how == CONSOLE_MODE_AUTO)
+ return mode_auto(mode);
+
+ if (how == CONSOLE_MODE_MAX) {
+ /* Note: MaxMode is the number of modes, not the last mode. */
+ if (ST->ConOut->Mode->MaxMode > 0)
+ *mode = ST->ConOut->Mode->MaxMode-1;
+ else
+ *mode = 0;
+ }
+
+ return change_mode(*mode);
+}
diff --git a/src/boot/efi/console.h b/src/boot/efi/console.h
index 5664a4e62f..bc2ee4959e 100644
--- a/src/boot/efi/console.h
+++ b/src/boot/efi/console.h
@@ -1,17 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2012 Harald Hoyer <harald@redhat.com>
*/
#ifndef __SDBOOT_CONSOLE_H
@@ -29,5 +18,13 @@
#define KEYCHAR(k) ((k) & 0xffff)
#define CHAR_CTRL(c) ((c) - 'a' + 1)
+enum console_mode_change_type {
+ CONSOLE_MODE_KEEP = 0,
+ CONSOLE_MODE_SET,
+ CONSOLE_MODE_AUTO,
+ CONSOLE_MODE_MAX,
+};
+
EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait);
+EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how);
#endif
diff --git a/src/boot/efi/disk.c b/src/boot/efi/disk.c
index af0f05c75d..a31b7bb478 100644
--- a/src/boot/efi/disk.c
+++ b/src/boot/efi/disk.c
@@ -1,17 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
#include <efi.h>
#include <efilib.h>
@@ -20,12 +7,12 @@
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]) {
EFI_DEVICE_PATH *device_path;
- EFI_STATUS r = EFI_NOT_FOUND;
/* export the device path this image is started from */
device_path = DevicePathFromHandle(handle);
if (device_path) {
- EFI_DEVICE_PATH *path, *paths;
+ _cleanup_freepool_ EFI_DEVICE_PATH *paths = NULL;
+ EFI_DEVICE_PATH *path;
paths = UnpackDevicePath(device_path);
for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
@@ -40,11 +27,9 @@ EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]) {
continue;
GuidToString(uuid, (EFI_GUID *)&drive->Signature);
- r = EFI_SUCCESS;
- break;
+ return EFI_SUCCESS;
}
- FreePool(paths);
}
- return r;
+ return EFI_NOT_FOUND;
}
diff --git a/src/boot/efi/disk.h b/src/boot/efi/disk.h
index c5894f8e4e..dfd9200ae1 100644
--- a/src/boot/efi/disk.h
+++ b/src/boot/efi/disk.h
@@ -1,17 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
#ifndef __SDBOOT_DISK_H
#define __SDBOOT_DISK_H
diff --git a/src/boot/efi/graphics.c b/src/boot/efi/graphics.c
index 29577c837a..6dbe9e2078 100644
--- a/src/boot/efi/graphics.c
+++ b/src/boot/efi/graphics.c
@@ -1,18 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- * Copyright (C) 2013 Intel Corporation
+ * Copyright © 2012 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2013 Intel Corporation
* Authored by Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
*/
diff --git a/src/boot/efi/graphics.h b/src/boot/efi/graphics.h
index 10e0c269ba..f42f934dd7 100644
--- a/src/boot/efi/graphics.h
+++ b/src/boot/efi/graphics.h
@@ -1,18 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- * Copyright (C) 2013 Intel Corporation
+ * Copyright © 2012 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2013 Intel Corporation
* Authored by Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
*/
diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c
index e8f7651324..d1605523d8 100644
--- a/src/boot/efi/linux.c
+++ b/src/boot/efi/linux.c
@@ -1,17 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
#include <efi.h>
#include <efilib.h>
@@ -128,7 +115,7 @@ EFI_STATUS linux_exec(EFI_HANDLE *image,
if (EFI_ERROR(err))
return err;
CopyMem((VOID *)(UINTN)addr, cmdline, cmdline_len);
- ((CHAR8 *)addr)[cmdline_len] = 0;
+ ((CHAR8 *)(UINTN)addr)[cmdline_len] = 0;
boot_setup->cmd_line_ptr = (UINT32)addr;
}
diff --git a/src/boot/efi/linux.h b/src/boot/efi/linux.h
index 3c11423591..54140a2207 100644
--- a/src/boot/efi/linux.h
+++ b/src/boot/efi/linux.h
@@ -1,17 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
#ifndef __SDBOOT_kernel_H
#define __SDBOOT_kernel_H
diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c
index 5aaffe8fa5..b6e3c44283 100644
--- a/src/boot/efi/measure.c
+++ b/src/boot/efi/measure.c
@@ -1,15 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
*/
#if ENABLE_TPM
@@ -188,7 +178,6 @@ typedef struct tdEFI_TCG2_PROTOCOL {
EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS GetResultOfSetActivePcrBanks;
} EFI_TCG2;
-
static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer,
UINTN buffer_size, const CHAR16 *description) {
EFI_STATUS status;
diff --git a/src/boot/efi/measure.h b/src/boot/efi/measure.h
index 63e0a738ce..99cf3b3fbd 100644
--- a/src/boot/efi/measure.h
+++ b/src/boot/efi/measure.h
@@ -1,15 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
*/
#ifndef __SDBOOT_MEASURE_H
#define __SDBOOT_MEASURE_H
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
index 2751b8da4f..8ec1fa7be4 100644
--- a/src/boot/efi/meson.build
+++ b/src/boot/efi/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
efi_headers = files('''
console.h
diff --git a/src/boot/efi/pe.c b/src/boot/efi/pe.c
index 3755a36a68..f1f947b183 100644
--- a/src/boot/efi/pe.c
+++ b/src/boot/efi/pe.c
@@ -1,17 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
#include <efi.h>
#include <efilib.h>
@@ -125,7 +112,7 @@ EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections
UINTN len;
UINTN headerlen;
EFI_STATUS err;
- CHAR8 *header = NULL;
+ _cleanup_freepool_ CHAR8 *header = NULL;
err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err))
@@ -166,9 +153,9 @@ EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections
goto out;
err = uefi_call_wrapper(handle->Read, 3, handle, &len, header);
- if (EFI_ERROR(err)) {
+ if (EFI_ERROR(err))
goto out;
- }
+
if (len != headerlen) {
err = EFI_LOAD_ERROR;
goto out;
@@ -176,8 +163,6 @@ EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections
err = pe_memory_locate_sections(header, sections, addrs, offsets, sizes);
out:
- if (header)
- FreePool(header);
uefi_call_wrapper(handle->Close, 1, handle);
return err;
}
diff --git a/src/boot/efi/pe.h b/src/boot/efi/pe.h
index 4a411f5d76..d3fc8ecf6b 100644
--- a/src/boot/efi/pe.h
+++ b/src/boot/efi/pe.h
@@ -1,17 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
#ifndef __SDBOOT_PEFILE_H
#define __SDBOOT_PEFILE_H
diff --git a/src/boot/efi/shim.c b/src/boot/efi/shim.c
index 6d7d814c5c..73ff861cb6 100644
--- a/src/boot/efi/shim.c
+++ b/src/boot/efi/shim.c
@@ -1,20 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
* Port to systemd-boot
- * Copyright 2017 Max Resch <resch.max@gmail.com>
+ * Copyright © 2017 Max Resch <resch.max@gmail.com>
*
* Security Policy Handling
- * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ * Copyright © 2012 <James.Bottomley@HansenPartnership.com>
* https://github.com/mjg59/efitools
*/
@@ -66,15 +56,11 @@ static BOOLEAN shim_validate(VOID *data, UINT32 size) {
}
BOOLEAN secure_boot_enabled(void) {
- CHAR8 *b;
+ _cleanup_freepool_ CHAR8 *b = NULL;
UINTN size;
- BOOLEAN result;
- if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
- result = *b > 0;
- FreePool(b);
- return result;
- }
+ if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS)
+ return *b > 0;
return FALSE;
}
@@ -156,12 +142,12 @@ static EFIAPI EFI_STATUS security2_policy_authentication (const EFI_SECURITY2_PR
static EFIAPI EFI_STATUS security_policy_authentication (const EFI_SECURITY_PROTOCOL *this, UINT32 authentication_status,
const EFI_DEVICE_PATH_PROTOCOL *device_path_const) {
EFI_STATUS status;
- EFI_DEVICE_PATH *dev_path;
+ _cleanup_freepool_ EFI_DEVICE_PATH *dev_path = NULL;
+ _cleanup_freepool_ CHAR16 *dev_path_str = NULL;
EFI_HANDLE h;
EFI_FILE *root;
- CHAR8 *file_buffer = NULL;
+ _cleanup_freepool_ CHAR8 *file_buffer = NULL;
UINTN file_size;
- CHAR16 *dev_path_str;
if (!device_path_const)
return EFI_INVALID_PARAMETER;
@@ -169,28 +155,23 @@ static EFIAPI EFI_STATUS security_policy_authentication (const EFI_SECURITY_PROT
dev_path = DuplicateDevicePath((EFI_DEVICE_PATH*) device_path_const);
status = uefi_call_wrapper(BS->LocateDevicePath, 3, (EFI_GUID*) &simple_fs_guid, &dev_path, &h);
- if (status != EFI_SUCCESS) {
- FreePool(dev_path);
+ if (status != EFI_SUCCESS)
return status;
- }
/* No need to check return value, this already happend in efi_main() */
root = LibOpenRoot(h);
dev_path_str = DevicePathToStr(dev_path);
- FreePool(dev_path);
- file_size = file_read(root, dev_path_str, 0, 0, &file_buffer);
- FreePool(dev_path_str);
+ status = file_read(root, dev_path_str, 0, 0, &file_buffer, &file_size);
+ if (EFI_ERROR(status))
+ return status;
uefi_call_wrapper(root->Close, 1, root);
if (shim_validate(file_buffer, file_size))
- status = EFI_SUCCESS;
- else
- /* Try using the platform's native policy.... */
- status = uefi_call_wrapper(esfas, 3, this, authentication_status, device_path_const);
- FreePool(file_buffer);
+ return EFI_SUCCESS;
- return status;
+ /* Try using the platform's native policy.... */
+ return uefi_call_wrapper(esfas, 3, this, authentication_status, device_path_const);
}
EFI_STATUS security_policy_install(void) {
diff --git a/src/boot/efi/shim.h b/src/boot/efi/shim.h
index d9ab135ae0..c847ae97a4 100644
--- a/src/boot/efi/shim.h
+++ b/src/boot/efi/shim.h
@@ -1,20 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
* Port to systemd-boot
- * Copyright 2017 Max Resch <resch.max@gmail.com>
+ * Copyright © 2017 Max Resch <resch.max@gmail.com>
*
* Security Policy Handling
- * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ * Copyright © 2012 <James.Bottomley@HansenPartnership.com>
* https://github.com/mjg59/efitools
*/
diff --git a/src/boot/efi/splash.c b/src/boot/efi/splash.c
index 32186d4e38..dd9cc29e1b 100644
--- a/src/boot/efi/splash.c
+++ b/src/boot/efi/splash.c
@@ -1,17 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2012 Harald Hoyer <harald@redhat.com>
*/
#include <efi.h>
@@ -260,7 +249,7 @@ EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_
struct bmp_map *map;
UINT8 *pixmap;
UINT64 blt_size;
- VOID *blt = NULL;
+ _cleanup_freepool_ VOID *blt = NULL;
UINTN x_pos = 0;
UINTN y_pos = 0;
EFI_STATUS err;
@@ -280,7 +269,7 @@ EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_
err = bmp_parse_header(content, len, &dib, &map, &pixmap);
if (EFI_ERROR(err))
- goto err;
+ return err;
if (dib->x < GraphicsOutput->Mode->Info->HorizontalResolution)
x_pos = (GraphicsOutput->Mode->Info->HorizontalResolution - dib->x) / 2;
@@ -303,20 +292,17 @@ EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_
blt, EfiBltVideoToBltBuffer, x_pos, y_pos, 0, 0,
dib->x, dib->y, 0);
if (EFI_ERROR(err))
- goto err;
+ return err;
err = bmp_to_blt(blt, dib, map, pixmap);
if (EFI_ERROR(err))
- goto err;
+ return err;
err = graphics_mode(TRUE);
if (EFI_ERROR(err))
- goto err;
+ return err;
- err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
- blt, EfiBltBufferToVideo, 0, 0, x_pos, y_pos,
- dib->x, dib->y, 0);
-err:
- FreePool(blt);
- return err;
+ return uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
+ blt, EfiBltBufferToVideo, 0, 0, x_pos, y_pos,
+ dib->x, dib->y, 0);
}
diff --git a/src/boot/efi/splash.h b/src/boot/efi/splash.h
index c7e9c7a78d..c9aa705b9a 100644
--- a/src/boot/efi/splash.h
+++ b/src/boot/efi/splash.h
@@ -1,17 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2012 Harald Hoyer <harald@redhat.com>
*/
#ifndef __SDBOOT_SPLASH_H
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
index ff45cebd45..4318a054a4 100644
--- a/src/boot/efi/stub.c
+++ b/src/boot/efi/stub.c
@@ -4,12 +4,6 @@
* the Free Software Foundation; either version 2.1 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
*/
#include <efi.h>
@@ -30,7 +24,7 @@ static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
EFI_LOADED_IMAGE *loaded_image;
- CHAR8 *b;
+ _cleanup_freepool_ CHAR8 *b = NULL;
UINTN size;
BOOLEAN secure = FALSE;
CHAR8 *sections[] = {
@@ -58,11 +52,10 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
return err;
}
- if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
+ if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS)
if (*b > 0)
secure = TRUE;
- FreePool(b);
- }
+
err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs);
if (EFI_ERROR(err)) {
Print(L"Unable to locate embedded .linux section: %r ", err);
@@ -91,7 +84,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
#if ENABLE_TPM
/* Try to log any options to the TPM, especially manually edited options */
err = tpm_log_event(SD_TPM_PCR,
- (EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions,
+ (EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
if (EFI_ERROR(err)) {
Print(L"Unable to add image options measurement: %r", err);
@@ -106,22 +99,26 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
/* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */
if (efivar_get_raw(&global_guid, L"LoaderImageIdentifier", &b, &size) != EFI_SUCCESS) {
- CHAR16 *loaded_image_path = DevicePathToStr(loaded_image->FilePath);
- efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE);
- FreePool(loaded_image_path);
+ _cleanup_freepool_ CHAR16 *s;
+
+ s = DevicePathToStr(loaded_image->FilePath);
+ efivar_set(L"LoaderImageIdentifier", s, FALSE);
}
/* if LoaderFirmwareInfo is not set, let's set it */
if (efivar_get_raw(&global_guid, L"LoaderFirmwareInfo", &b, &size) != EFI_SUCCESS) {
- CHAR16 *loader_firmware_info = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
- efivar_set(L"LoaderFirmwareInfo", loader_firmware_info, FALSE);
- FreePool(loader_firmware_info);
+ _cleanup_freepool_ CHAR16 *s;
+
+ s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
+ efivar_set(L"LoaderFirmwareInfo", s, FALSE);
}
+
/* ditto for LoaderFirmwareType */
if (efivar_get_raw(&global_guid, L"LoaderFirmwareType", &b, &size) != EFI_SUCCESS) {
- CHAR16 *loader_firmware_type = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
- efivar_set(L"LoaderFirmwareType", loader_firmware_type, FALSE);
- FreePool(loader_firmware_type);
+ _cleanup_freepool_ CHAR16 *s;
+
+ s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
+ efivar_set(L"LoaderFirmwareType", s, FALSE);
}
/* add StubInfo */
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
index b165f31005..f513e2fd13 100644
--- a/src/boot/efi/util.c
+++ b/src/boot/efi/util.c
@@ -1,17 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2012 Harald Hoyer <harald@redhat.com>
*/
#include <efi.h>
@@ -115,7 +104,7 @@ EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) {
}
EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value) {
- CHAR8 *buf;
+ _cleanup_freepool_ CHAR8 *buf = NULL;
CHAR16 *val;
UINTN size;
EFI_STATUS err;
@@ -125,29 +114,26 @@ EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value) {
return err;
val = StrDuplicate((CHAR16 *)buf);
- if (!val) {
- FreePool(buf);
+ if (!val)
return EFI_OUT_OF_RESOURCES;
- }
*value = val;
return EFI_SUCCESS;
}
EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i) {
- CHAR16 *val;
+ _cleanup_freepool_ CHAR16 *val = NULL;
EFI_STATUS err;
err = efivar_get(name, &val);
- if (!EFI_ERROR(err)) {
+ if (!EFI_ERROR(err))
*i = Atoi(val);
- FreePool(val);
- }
+
return err;
}
EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size) {
- CHAR8 *buf;
+ _cleanup_freepool_ CHAR8 *buf = NULL;
UINTN l;
EFI_STATUS err;
@@ -159,12 +145,12 @@ EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer,
err = uefi_call_wrapper(RT->GetVariable, 5, name, (EFI_GUID *)vendor, NULL, &l, buf);
if (!EFI_ERROR(err)) {
*buffer = buf;
+ buf = NULL;
if (size)
*size = l;
- } else
- FreePool(buf);
- return err;
+ }
+ return err;
}
VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) {
@@ -304,25 +290,21 @@ CHAR8 *strchra(CHAR8 *s, CHAR8 c) {
return NULL;
}
-INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content) {
+EFI_STATUS file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size) {
EFI_FILE_HANDLE handle;
- CHAR8 *buf;
- UINTN buflen;
+ _cleanup_freepool_ CHAR8 *buf = NULL;
EFI_STATUS err;
- UINTN len;
err = uefi_call_wrapper(dir->Open, 5, dir, &handle, name, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err))
return err;
if (size == 0) {
- EFI_FILE_INFO *info;
+ _cleanup_freepool_ EFI_FILE_INFO *info;
info = LibFileInfo(handle);
- buflen = info->FileSize+1;
- FreePool(info);
- } else
- buflen = size;
+ size = info->FileSize+1;
+ }
if (off > 0) {
err = uefi_call_wrapper(handle->SetPosition, 2, handle, off);
@@ -330,17 +312,16 @@ INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 *
return err;
}
- buf = AllocatePool(buflen);
- err = uefi_call_wrapper(handle->Read, 3, handle, &buflen, buf);
+ buf = AllocatePool(size + 1);
+ err = uefi_call_wrapper(handle->Read, 3, handle, &size, buf);
if (!EFI_ERROR(err)) {
- buf[buflen] = '\0';
+ buf[size] = '\0';
*content = buf;
- len = buflen;
- } else {
- len = err;
- FreePool(buf);
+ buf = NULL;
+ if (content_size)
+ *content_size = size;
}
-
uefi_call_wrapper(handle->Close, 1, handle);
- return len;
+
+ return err;
}
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
index 35150aea76..1f64b026dc 100644
--- a/src/boot/efi/util.h
+++ b/src/boot/efi/util.h
@@ -1,17 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
+ * Copyright © 2012 Harald Hoyer <harald@redhat.com>
*/
#ifndef __SDBOOT_UTIL_H
@@ -45,5 +34,12 @@ CHAR8 *strchra(CHAR8 *s, CHAR8 c);
CHAR16 *stra_to_path(CHAR8 *stra);
CHAR16 *stra_to_str(CHAR8 *stra);
-INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content);
+EFI_STATUS file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size);
#endif
+
+static inline void FreePoolp(void *p) {
+ FreePool(*(void**) p);
+}
+
+#define _cleanup_(x) __attribute__((cleanup(x)))
+#define _cleanup_freepool_ _cleanup_(FreePoolp)
diff --git a/src/busctl/busctl-introspect.c b/src/busctl/busctl-introspect.c
index 54d6e07d2c..4af3481a5f 100644
--- a/src/busctl/busctl-introspect.c
+++ b/src/busctl/busctl-introspect.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-bus.h"
@@ -275,10 +257,9 @@ static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth
free(node_path);
- if (name[0] == '/') {
- node_path = name;
- name = NULL;
- } else {
+ if (name[0] == '/')
+ node_path = TAKE_PTR(name);
+ else {
if (endswith(prefix, "/"))
node_path = strappend(prefix, name);
@@ -558,7 +539,6 @@ static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth
break;
-
case STATE_SIGNAL_ARG:
if (t == XML_ATTRIBUTE_NAME) {
diff --git a/src/busctl/busctl-introspect.h b/src/busctl/busctl-introspect.h
index a27a1c8f9d..b17800e83e 100644
--- a/src/busctl/busctl-introspect.h
+++ b/src/busctl/busctl-introspect.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
typedef struct XMLIntrospectOps {
diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c
index ae132dffbe..f9b23514c1 100644
--- a/src/busctl/busctl.c
+++ b/src/busctl/busctl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
#include <stdio_ext.h>
@@ -32,6 +14,7 @@
#include "busctl-introspect.h"
#include "escape.h"
#include "fd-util.h"
+#include "fileio.h"
#include "locale-util.h"
#include "log.h"
#include "pager.h"
@@ -42,6 +25,7 @@
#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
+#include "verbs.h"
static bool arg_no_pager = false;
static bool arg_legend = true;
@@ -52,7 +36,7 @@ static bool arg_activatable = false;
static bool arg_show_machine = false;
static char **arg_matches = NULL;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static char *arg_host = NULL;
+static const char *arg_host = NULL;
static bool arg_user = false;
static size_t arg_snaplen = 4096;
static bool arg_list = false;
@@ -68,7 +52,81 @@ static usec_t arg_timeout = 0;
#define NAME_IS_ACQUIRED INT_TO_PTR(1)
#define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
-static int list_bus_names(sd_bus *bus, char **argv) {
+static int acquire_bus(bool set_monitor, sd_bus **ret) {
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ int r;
+
+ r = sd_bus_new(&bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate bus: %m");
+
+ if (set_monitor) {
+ r = sd_bus_set_monitor(bus, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set monitor mode: %m");
+
+ r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable credentials: %m");
+
+ r = sd_bus_negotiate_timestamp(bus, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable timestamps: %m");
+
+ r = sd_bus_negotiate_fds(bus, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable fds: %m");
+ }
+
+ r = sd_bus_set_bus_client(bus, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set bus client: %m");
+
+ r = sd_bus_set_watch_bind(bus, arg_watch_bind);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set watch-bind setting to '%s': %m", yes_no(arg_watch_bind));
+
+ if (arg_address)
+ r = sd_bus_set_address(bus, arg_address);
+ else {
+ switch (arg_transport) {
+
+ case BUS_TRANSPORT_LOCAL:
+ if (arg_user) {
+ bus->is_user = true;
+ r = bus_set_address_user(bus);
+ } else {
+ bus->is_system = true;
+ r = bus_set_address_system(bus);
+ }
+ break;
+
+ case BUS_TRANSPORT_REMOTE:
+ r = bus_set_address_system_remote(bus, arg_host);
+ break;
+
+ case BUS_TRANSPORT_MACHINE:
+ r = bus_set_address_system_machine(bus, arg_host);
+ break;
+
+ default:
+ assert_not_reached("Hmm, unknown transport type.");
+ }
+ }
+ if (r < 0)
+ return log_error_errno(r, "Failed to set address: %m");
+
+ r = sd_bus_start(bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to bus: %m");
+
+ *ret = TAKE_PTR(bus);
+
+ return 0;
+}
+
+static int list_bus_names(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_strv_free_ char **acquired = NULL, **activatable = NULL;
_cleanup_free_ char **merged = NULL;
_cleanup_hashmap_free_ Hashmap *names = NULL;
@@ -80,16 +138,18 @@ static int list_bus_names(sd_bus *bus, char **argv) {
char *k;
Iterator iterator;
- assert(bus);
-
if (!arg_unique && !arg_acquired && !arg_activatable)
arg_unique = arg_acquired = arg_activatable = true;
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
+
r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL);
if (r < 0)
return log_error_errno(r, "Failed to list names: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
names = hashmap_new(&string_hash_ops);
if (!names)
@@ -337,7 +397,7 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p
if (many)
printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r));
else
- log_error("Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r));
+ log_error_errno(r, "Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r));
return r;
}
@@ -404,7 +464,7 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
p = NULL;
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
l = set_get_strv(done);
if (!l)
@@ -418,14 +478,19 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
return r;
}
-static int tree(sd_bus *bus, char **argv) {
+static int tree(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
char **i;
int r = 0;
if (!arg_unique && !arg_acquired)
arg_acquired = true;
- if (strv_length(argv) <= 1) {
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
+
+ if (argc <= 1) {
_cleanup_strv_free_ char **names = NULL;
bool not_first = false;
@@ -433,7 +498,7 @@ static int tree(sd_bus *bus, char **argv) {
if (r < 0)
return log_error_errno(r, "Failed to get name list: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
STRV_FOREACH(i, names) {
int q;
@@ -463,7 +528,7 @@ static int tree(sd_bus *bus, char **argv) {
printf("\n");
if (argv[2]) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
}
@@ -845,11 +910,7 @@ static int on_property(const char *interface, const char *name, const char *sign
return 0;
}
-static const char *strdash(const char *x) {
- return isempty(x) ? "-" : x;
-}
-
-static int introspect(sd_bus *bus, char **argv) {
+static int introspect(int argc, char **argv, void *userdata) {
static const struct hash_ops member_hash_ops = {
.hash = member_hash_func,
.compare = member_compare_func,
@@ -862,27 +923,19 @@ static int introspect(sd_bus *bus, char **argv) {
.on_property = on_property,
};
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_xml = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(member_set_freep) Set *members = NULL;
+ unsigned name_width, type_width, signature_width, result_width, j, k = 0;
+ Member *m, **sorted = NULL;
Iterator i;
- Member *m;
const char *xml;
int r;
- unsigned name_width, type_width, signature_width, result_width;
- Member **sorted = NULL;
- unsigned k = 0, j, n_args;
- n_args = strv_length(argv);
- if (n_args < 3) {
- log_error("Requires service and object path argument.");
- return -EINVAL;
- }
-
- if (n_args > 4) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
members = set_new(&member_hash_ops);
if (!members)
@@ -977,7 +1030,7 @@ static int introspect(sd_bus *bus, char **argv) {
return bus_log_parse_error(r);
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
name_width = STRLEN("NAME");
type_width = STRLEN("TYPE");
@@ -1043,15 +1096,15 @@ static int introspect(sd_bus *bus, char **argv) {
rv = ellipsized;
} else
- rv = strdash(m->result);
+ rv = empty_to_dash(m->result);
printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n",
is_interface ? ansi_highlight() : "",
is_interface ? "" : ".",
- - !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name),
+ - !is_interface + (int) name_width, empty_to_dash(streq_ptr(m->type, "interface") ? m->interface : m->name),
is_interface ? ansi_normal() : "",
- (int) type_width, strdash(m->type),
- (int) signature_width, strdash(m->signature),
+ (int) type_width, empty_to_dash(m->type),
+ (int) signature_width, empty_to_dash(m->signature),
(int) result_width, rv,
(m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"),
(m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "",
@@ -1072,7 +1125,8 @@ static int message_pcap(sd_bus_message *m, FILE *f) {
return bus_message_pcap_frame(m, arg_snaplen, f);
}
-static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) {
+static int monitor(int argc, char **argv, int (*dump)(sd_bus_message *m, FILE *f)) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char **i;
@@ -1081,6 +1135,10 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
bool is_monitor = false;
int r;
+ r = acquire_bus(true, &bus);
+ if (r < 0)
+ return r;
+
/* upgrade connection; it's not used for anything else after this call */
r = sd_bus_message_new_method_call(bus, &message, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
if (r < 0)
@@ -1131,10 +1189,8 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
return bus_log_create_error(r);
r = sd_bus_call(bus, message, arg_timeout, &error, NULL);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "%s", bus_error_message(&error, r));
r = sd_bus_get_unique_name(bus, &unique_name);
if (r < 0)
@@ -1187,7 +1243,11 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
}
}
-static int capture(sd_bus *bus, char *argv[]) {
+static int verb_monitor(int argc, char **argv, void *userdata) {
+ return monitor(argc, argv, message_dump);
+}
+
+static int verb_capture(int argc, char **argv, void *userdata) {
int r;
if (isatty(fileno(stdout)) > 0) {
@@ -1197,31 +1257,28 @@ static int capture(sd_bus *bus, char *argv[]) {
bus_pcap_header(arg_snaplen, stdout);
- r = monitor(bus, argv, message_pcap);
+ r = monitor(argc, argv, message_pcap);
if (r < 0)
return r;
- if (ferror(stdout)) {
- log_error("Couldn't write capture file.");
- return -EIO;
- }
+ r = fflush_and_check(stdout);
+ if (r < 0)
+ return log_error_errno(r, "Couldn't write capture file: %m");
return r;
}
-static int status(sd_bus *bus, char *argv[]) {
+static int status(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
int r;
- assert(bus);
-
- if (strv_length(argv) > 2) {
- log_error("Expects no or one argument.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
- if (argv[1]) {
+ if (!isempty(argv[1])) {
r = parse_pid(argv[1], &pid);
if (r < 0)
r = sd_bus_get_name_creds(
@@ -1295,10 +1352,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
case SD_BUS_TYPE_BOOLEAN:
r = parse_boolean(v);
- if (r < 0) {
- log_error("Failed to parse as boolean: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as boolean: %s", v);
r = sd_bus_message_append_basic(m, t, &r);
break;
@@ -1307,10 +1362,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
uint8_t z;
r = safe_atou8(v, &z);
- if (r < 0) {
- log_error("Failed to parse as byte (unsigned 8bit integer): %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as byte (unsigned 8bit integer): %s", v);
r = sd_bus_message_append_basic(m, t, &z);
break;
@@ -1320,10 +1373,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
int16_t z;
r = safe_atoi16(v, &z);
- if (r < 0) {
- log_error("Failed to parse as signed 16bit integer: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as signed 16bit integer: %s", v);
r = sd_bus_message_append_basic(m, t, &z);
break;
@@ -1333,10 +1384,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
uint16_t z;
r = safe_atou16(v, &z);
- if (r < 0) {
- log_error("Failed to parse as unsigned 16bit integer: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as unsigned 16bit integer: %s", v);
r = sd_bus_message_append_basic(m, t, &z);
break;
@@ -1346,10 +1395,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
int32_t z;
r = safe_atoi32(v, &z);
- if (r < 0) {
- log_error("Failed to parse as signed 32bit integer: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as signed 32bit integer: %s", v);
r = sd_bus_message_append_basic(m, t, &z);
break;
@@ -1359,10 +1406,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
uint32_t z;
r = safe_atou32(v, &z);
- if (r < 0) {
- log_error("Failed to parse as unsigned 32bit integer: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as unsigned 32bit integer: %s", v);
r = sd_bus_message_append_basic(m, t, &z);
break;
@@ -1372,10 +1417,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
int64_t z;
r = safe_atoi64(v, &z);
- if (r < 0) {
- log_error("Failed to parse as signed 64bit integer: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as signed 64bit integer: %s", v);
r = sd_bus_message_append_basic(m, t, &z);
break;
@@ -1385,24 +1428,19 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
uint64_t z;
r = safe_atou64(v, &z);
- if (r < 0) {
- log_error("Failed to parse as unsigned 64bit integer: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as unsigned 64bit integer: %s", v);
r = sd_bus_message_append_basic(m, t, &z);
break;
}
-
case SD_BUS_TYPE_DOUBLE: {
double z;
r = safe_atod(v, &z);
- if (r < 0) {
- log_error("Failed to parse as double precision floating point: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse as double precision floating point: %s", v);
r = sd_bus_message_append_basic(m, t, &z);
break;
@@ -1420,16 +1458,12 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
size_t k;
r = safe_atou32(v, &n);
- if (r < 0) {
- log_error("Failed to parse number of array entries: %s", v);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse number of array entries: %s", v);
r = signature_element_length(signature, &k);
- if (r < 0) {
- log_error("Invalid array signature.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Invalid array signature.");
{
unsigned i;
@@ -1474,10 +1508,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
p--;
r = signature_element_length(signature, &k);
- if (r < 0) {
- log_error("Invalid struct/dict entry signature.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Invalid struct/dict entry signature.");
{
char s[k-1];
@@ -1516,17 +1548,15 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
return 0;
}
-static int call(sd_bus *bus, char *argv[]) {
+static int call(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
int r;
- assert(bus);
-
- if (strv_length(argv) < 5) {
- log_error("Expects at least four arguments.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]);
if (r < 0)
@@ -1561,19 +1591,15 @@ static int call(sd_bus *bus, char *argv[]) {
if (!arg_expect_reply) {
r = sd_bus_send(bus, m, NULL);
- if (r < 0) {
- log_error("Failed to send message.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to send message: %m");
return 0;
}
r = sd_bus_call(bus, m, arg_timeout, &error, &reply);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "%s", bus_error_message(&error, r));
r = sd_bus_message_is_empty(reply);
if (r < 0)
@@ -1582,7 +1608,7 @@ static int call(sd_bus *bus, char *argv[]) {
if (r == 0 && !arg_quiet) {
if (arg_verbose) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = bus_message_dump(reply, stdout, 0);
if (r < 0)
@@ -1603,19 +1629,15 @@ static int call(sd_bus *bus, char *argv[]) {
return 0;
}
-static int get_property(sd_bus *bus, char *argv[]) {
+static int get_property(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned n;
char **i;
int r;
- assert(bus);
-
- n = strv_length(argv);
- if (n < 5) {
- log_error("Expects at least four arguments.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
STRV_FOREACH(i, argv + 4) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -1623,10 +1645,8 @@ static int get_property(sd_bus *bus, char *argv[]) {
char type;
r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "%s", bus_error_message(&error, r));
r = sd_bus_message_peek_type(reply, &type, &contents);
if (r < 0)
@@ -1637,7 +1657,7 @@ static int get_property(sd_bus *bus, char *argv[]) {
return bus_log_parse_error(r);
if (arg_verbose) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
if (r < 0)
@@ -1661,20 +1681,16 @@ static int get_property(sd_bus *bus, char *argv[]) {
return 0;
}
-static int set_property(sd_bus *bus, char *argv[]) {
+static int set_property(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned n;
char **p;
int r;
- assert(bus);
-
- n = strv_length(argv);
- if (n < 6) {
- log_error("Expects at least five arguments.");
- return -EINVAL;
- }
+ r = acquire_bus(false, &bus);
+ if (r < 0)
+ return r;
r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set");
if (r < 0)
@@ -1688,7 +1704,7 @@ static int set_property(sd_bus *bus, char *argv[]) {
if (r < 0)
return bus_log_create_error(r);
- p = argv+6;
+ p = argv + 6;
r = message_append_cmdline(m, argv[5], &p);
if (r < 0)
return r;
@@ -1703,10 +1719,8 @@ static int set_property(sd_bus *bus, char *argv[]) {
}
r = sd_bus_call(bus, m, arg_timeout, &error, NULL);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "%s", bus_error_message(&error, r));
return 0;
}
@@ -1759,6 +1773,10 @@ static int help(void) {
return 0;
}
+static int verb_help(int argc, char **argv, void *userdata) {
+ return help();
+}
+
static int parse_argv(int argc, char *argv[]) {
enum {
@@ -1872,10 +1890,8 @@ static int parse_argv(int argc, char *argv[]) {
uint64_t sz;
r = parse_size(optarg, 1024, &sz);
- if (r < 0) {
- log_error("Failed to parse size: %s", optarg);
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse size: %s", optarg);
if ((uint64_t) (size_t) sz != sz) {
log_error("Size out of range.");
@@ -1910,63 +1926,49 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_EXPECT_REPLY:
r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --expect-reply= parameter.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --expect-reply= parameter: %s", optarg);
- arg_expect_reply = !!r;
+ arg_expect_reply = r;
break;
-
case ARG_AUTO_START:
r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --auto-start= parameter.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --auto-start= parameter: %s", optarg);
- arg_auto_start = !!r;
+ arg_auto_start = r;
break;
-
case ARG_ALLOW_INTERACTIVE_AUTHORIZATION:
r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --allow-interactive-authorization= parameter.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --allow-interactive-authorization= parameter: %s", optarg);
- arg_allow_interactive_authorization = !!r;
+ arg_allow_interactive_authorization = r;
break;
case ARG_TIMEOUT:
r = parse_sec(optarg, &arg_timeout);
- if (r < 0) {
- log_error("Failed to parse --timeout= parameter.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --timeout= parameter: %s", optarg);
break;
case ARG_AUGMENT_CREDS:
r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --augment-creds= parameter.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --augment-creds= parameter: %s", optarg);
- arg_augment_creds = !!r;
+ arg_augment_creds = r;
break;
case ARG_WATCH_BIND:
r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --watch-bind= parameter.");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --watch-bind= parameter: %s", optarg);
- arg_watch_bind = !!r;
+ arg_watch_bind = r;
break;
case '?':
@@ -1979,46 +1981,26 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
-static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
- assert(bus);
-
- if (optind >= argc ||
- streq(argv[optind], "list"))
- return list_bus_names(bus, argv + optind);
-
- if (streq(argv[optind], "monitor"))
- return monitor(bus, argv + optind, message_dump);
-
- if (streq(argv[optind], "capture"))
- return capture(bus, argv + optind);
-
- if (streq(argv[optind], "status"))
- return status(bus, argv + optind);
-
- if (streq(argv[optind], "tree"))
- return tree(bus, argv + optind);
-
- if (streq(argv[optind], "introspect"))
- return introspect(bus, argv + optind);
-
- if (streq(argv[optind], "call"))
- return call(bus, argv + optind);
-
- if (streq(argv[optind], "get-property"))
- return get_property(bus, argv + optind);
-
- if (streq(argv[optind], "set-property"))
- return set_property(bus, argv + optind);
-
- if (streq(argv[optind], "help"))
- return help();
+static int busctl_main(int argc, char *argv[]) {
+
+ static const Verb verbs[] = {
+ { "list", VERB_ANY, 1, VERB_DEFAULT, list_bus_names },
+ { "status", VERB_ANY, 2, 0, status },
+ { "monitor", VERB_ANY, VERB_ANY, 0, verb_monitor },
+ { "capture", VERB_ANY, VERB_ANY, 0, verb_capture },
+ { "tree", VERB_ANY, VERB_ANY, 0, tree },
+ { "introspect", 3, 4, 0, introspect },
+ { "call", 5, VERB_ANY, 0, call },
+ { "get-property", 5, VERB_ANY, 0, get_property },
+ { "set-property", 6, VERB_ANY, 0, set_property },
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help },
+ {}
+ };
- log_error("Unknown command '%s'", argv[optind]);
- return -EINVAL;
+ return dispatch_verb(argc, argv, verbs, NULL);
}
int main(int argc, char *argv[]) {
- sd_bus *bus = NULL;
int r;
log_parse_environment();
@@ -2028,98 +2010,14 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto finish;
- r = sd_bus_new(&bus);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate bus: %m");
- goto finish;
- }
-
- if (STRPTR_IN_SET(argv[optind], "monitor", "capture")) {
-
- r = sd_bus_set_monitor(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to set monitor mode: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL);
- if (r < 0) {
- log_error_errno(r, "Failed to enable credentials: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_timestamp(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to enable timestamps: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_fds(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to enable fds: %m");
- goto finish;
- }
- }
-
- r = sd_bus_set_bus_client(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to set bus client: %m");
- goto finish;
- }
-
- r = sd_bus_set_watch_bind(bus, arg_watch_bind);
- if (r < 0) {
- log_error_errno(r, "Failed to set watch-bind setting to '%s': %m", yes_no(arg_watch_bind));
- goto finish;
- }
-
- if (arg_address)
- r = sd_bus_set_address(bus, arg_address);
- else {
- switch (arg_transport) {
-
- case BUS_TRANSPORT_LOCAL:
- if (arg_user) {
- bus->is_user = true;
- r = bus_set_address_user(bus);
- } else {
- bus->is_system = true;
- r = bus_set_address_system(bus);
- }
- break;
-
- case BUS_TRANSPORT_REMOTE:
- r = bus_set_address_system_remote(bus, arg_host);
- break;
-
- case BUS_TRANSPORT_MACHINE:
- r = bus_set_address_system_machine(bus, arg_host);
- break;
-
- default:
- assert_not_reached("Hmm, unknown transport type.");
- }
- }
- if (r < 0) {
- log_error_errno(r, "Failed to set address: %m");
- goto finish;
- }
-
- r = sd_bus_start(bus);
- if (r < 0) {
- log_error_errno(r, "Failed to connect to bus: %m");
- goto finish;
- }
-
- r = busctl_main(bus, argc, argv);
+ r = busctl_main(argc, argv);
finish:
/* make sure we terminate the bus connection first, and then close the
* pager, see issue #3543 for the details. */
- sd_bus_flush_close_unref(bus);
pager_close();
- strv_free(arg_matches);
+ arg_matches = strv_free(arg_matches);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index bd8c6a0059..9c2f591dc6 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
@@ -162,7 +144,7 @@ static void show_cg_info(const char *controller, const char *path) {
if (cg_all_unified() == 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER))
printf("Controller %s; ", controller);
- printf("Control group %s:\n", isempty(path) ? "/" : path);
+ printf("Control group %s:\n", empty_to_root(path));
fflush(stdout);
}
@@ -176,11 +158,9 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto finish;
- if (!arg_no_pager) {
- r = pager_open(arg_no_pager, false);
- if (r > 0 && arg_full < 0)
- arg_full = true;
- }
+ r = pager_open(arg_no_pager, false);
+ if (r > 0 && arg_full < 0)
+ arg_full = true;
output_flags =
arg_all * OUTPUT_SHOW_ALL |
@@ -256,7 +236,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- path_kill_slashes(j);
+ path_simplify(j, false);
path = j;
} else
path = root;
diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c
index 05d12ebb41..27a28d1414 100644
--- a/src/cgroups-agent/cgroups-agent.c
+++ b/src/cgroups-agent/cgroups-agent.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdlib.h>
#include <sys/socket.h>
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index 4cab5a253c..8dda08ab4c 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <alloca.h>
#include <errno.h>
@@ -147,7 +129,7 @@ static bool is_root_cgroup(const char *path) {
if (detect_container() > 0)
return false;
- return isempty(path) || path_equal(path, "/");
+ return empty_or_root(path);
}
static int process(
@@ -483,7 +465,7 @@ static int refresh_one(
if (!p)
return -ENOMEM;
- path_kill_slashes(p);
+ path_simplify(p, false);
r = refresh_one(controller, p, a, b, iteration, depth + 1, &child);
if (r < 0)
@@ -542,10 +524,6 @@ static int refresh(const char *root, Hashmap *a, Hashmap *b, unsigned iteration)
return 0;
}
-static const char *empty_to_slash(const char *p) {
- return isempty(p) ? "/" : p;
-}
-
static int group_compare(const void*a, const void *b) {
const Group *x = *(Group**)a, *y = *(Group**)b;
@@ -555,9 +533,9 @@ static int group_compare(const void*a, const void *b) {
* recursive summing is off, since that is actually
* not accumulative for all children. */
- if (path_startswith(empty_to_slash(y->path), empty_to_slash(x->path)))
+ if (path_startswith(empty_to_root(y->path), empty_to_root(x->path)))
return -1;
- if (path_startswith(empty_to_slash(x->path), empty_to_slash(y->path)))
+ if (path_startswith(empty_to_root(x->path), empty_to_root(y->path)))
return 1;
}
@@ -640,7 +618,7 @@ static void display(Hashmap *a) {
if (!terminal_is_dumb())
fputs(ANSI_HOME_CLEAR, stdout);
- array = alloca(sizeof(Group*) * hashmap_size(a));
+ array = newa(Group*, hashmap_size(a));
HASHMAP_FOREACH(g, a, i)
if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid)
@@ -706,7 +684,7 @@ static void display(Hashmap *a) {
g = array[j];
- path = empty_to_slash(g->path);
+ path = empty_to_root(g->path);
ellipsized = ellipsize(path, path_columns, 33);
printf("%-*s", path_columns, ellipsized ?: path);
diff --git a/src/core/all-units.h b/src/core/all-units.h
new file mode 100644
index 0000000000..ed8350ebe0
--- /dev/null
+++ b/src/core/all-units.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "unit.h"
+
+#include "automount.h"
+#include "device.h"
+#include "path.h"
+#include "scope.h"
+#include "service.h"
+#include "slice.h"
+#include "socket.h"
+#include "swap.h"
+#include "target.h"
+#include "timer.h"
diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c
index 60e79035af..fdef433923 100644
--- a/src/core/audit-fd.c
+++ b/src/core/audit-fd.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <errno.h>
diff --git a/src/core/audit-fd.h b/src/core/audit-fd.h
index 43f4f193d8..8c1e471b96 100644
--- a/src/core/audit-fd.h
+++ b/src/core/audit-fd.h
@@ -1,24 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int get_audit_fd(void);
void close_audit_fd(void);
diff --git a/src/core/automount.c b/src/core/automount.c
index 01a6ff806e..1b96a52c00 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -185,16 +167,16 @@ static int automount_verify(Automount *a) {
if (path_equal(a->where, "/")) {
log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
r = unit_name_from_path(a->where, ".automount", &e);
if (r < 0)
- return log_unit_error(UNIT(a), "Failed to generate unit name from path: %m");
+ return log_unit_error_errno(UNIT(a), r, "Failed to generate unit name from path: %m");
if (!unit_has_name(UNIT(a), e)) {
log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
return 0;
@@ -212,7 +194,7 @@ static int automount_set_where(Automount *a) {
if (r < 0)
return r;
- path_kill_slashes(a->where);
+ path_simplify(a->where, false);
return 1;
}
@@ -265,7 +247,7 @@ static void automount_set_state(Automount *a, AutomountState state) {
if (state != old_state)
log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), automount_state_to_string(state));
- unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
+ unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], 0);
}
static int automount_coldplug(Unit *u) {
@@ -346,7 +328,7 @@ static int open_dev_autofs(Manager *m) {
if (m->dev_autofs_fd >= 0)
return m->dev_autofs_fd;
- label_fix("/dev/autofs", false, false);
+ (void) label_fix("/dev/autofs", 0);
m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY);
if (m->dev_autofs_fd < 0)
@@ -429,7 +411,7 @@ static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, usec_t usec) {
param.timeout.timeout = 0;
else
/* Convert to seconds, rounding up. */
- param.timeout.timeout = (usec + USEC_PER_SEC - 1) / USEC_PER_SEC;
+ param.timeout.timeout = DIV_ROUND_UP(usec, USEC_PER_SEC);
if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
return -errno;
diff --git a/src/core/automount.h b/src/core/automount.h
index b8be4d316e..21dd1c0774 100644
--- a/src/core/automount.h
+++ b/src/core/automount.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Automount Automount;
#include "unit.h"
@@ -58,3 +39,5 @@ extern const UnitVTable automount_vtable;
const char* automount_result_to_string(AutomountResult i) _const_;
AutomountResult automount_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(AUTOMOUNT, Automount);
diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c
index deebafbf47..8b66ef73dc 100644
--- a/src/core/bpf-firewall.c
+++ b/src/core/bpf-firewall.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <assert.h>
@@ -311,8 +293,7 @@ static int bpf_firewall_compile_bpf(
return r;
} while (false);
- *ret = p;
- p = NULL;
+ *ret = TAKE_PTR(p);
return 0;
}
@@ -743,8 +724,7 @@ int bpf_firewall_supported(void) {
.attach_bpf_fd = -1,
};
- r = bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
- if (r < 0) {
+ if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0) {
if (errno != EBADF) {
log_debug_errno(errno, "Didn't get EBADF from BPF_PROG_ATTACH, BPF firewalling is not supported: %m");
return supported = BPF_FIREWALL_UNSUPPORTED;
@@ -768,8 +748,7 @@ int bpf_firewall_supported(void) {
.attach_flags = BPF_F_ALLOW_MULTI,
};
- r = bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
- if (r < 0) {
+ if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0) {
if (errno == EBADF) {
log_debug_errno(errno, "Got EBADF when using BPF_F_ALLOW_MULTI, which indicates it is supported. Yay!");
return supported = BPF_FIREWALL_SUPPORTED_WITH_MULTI;
diff --git a/src/core/bpf-firewall.h b/src/core/bpf-firewall.h
index a0658e3b86..e2d08a0fc8 100644
--- a/src/core/bpf-firewall.h
+++ b/src/core/bpf-firewall.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <inttypes.h>
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index a923ab8a76..bb02436203 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <fnmatch.h>
@@ -24,6 +6,7 @@
#include "alloc-util.h"
#include "blockdev-util.h"
#include "bpf-firewall.h"
+#include "btrfs-util.h"
#include "bus-error.h"
#include "cgroup-util.h"
#include "cgroup.h"
@@ -53,7 +36,7 @@ bool manager_owns_root_cgroup(Manager *m) {
if (detect_container() > 0)
return false;
- return isempty(m->cgroup_root) || path_equal(m->cgroup_root, "/");
+ return empty_or_root(m->cgroup_root);
}
bool unit_has_root_cgroup(Unit *u) {
@@ -319,32 +302,36 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
}
}
-static int lookup_block_device(const char *p, dev_t *dev) {
+static int lookup_block_device(const char *p, dev_t *ret) {
struct stat st;
int r;
assert(p);
- assert(dev);
+ assert(ret);
- r = stat(p, &st);
- if (r < 0)
- return log_warning_errno(errno, "Couldn't stat device %s: %m", p);
+ if (stat(p, &st) < 0)
+ return log_warning_errno(errno, "Couldn't stat device '%s': %m", p);
if (S_ISBLK(st.st_mode))
- *dev = st.st_rdev;
- else if (major(st.st_dev) != 0) {
- /* If this is not a device node then find the block
- * device this file is stored on */
- *dev = st.st_dev;
-
- /* If this is a partition, try to get the originating
- * block device */
- (void) block_get_whole_disk(*dev, dev);
- } else {
- log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
- return -ENODEV;
+ *ret = st.st_rdev;
+ else if (major(st.st_dev) != 0)
+ *ret = st.st_dev; /* If this is not a device node then use the block device this file is stored on */
+ else {
+ /* If this is btrfs, getting the backing block device is a bit harder */
+ r = btrfs_get_block_device(p, ret);
+ if (r < 0 && r != -ENOTTY)
+ return log_warning_errno(r, "Failed to determine block device backing btrfs file system '%s': %m", p);
+ if (r == -ENOTTY) {
+ log_warning("'%s' is not a block device node, and file system block device cannot be determined or is not local.", p);
+ return -ENODEV;
+ }
}
+ /* If this is a LUKS device, try to get the originating block device */
+ (void) block_get_originating(*ret, ret);
+
+ /* If this is a partition, try to get the originating block device */
+ (void) block_get_whole_disk(*ret, ret);
return 0;
}
@@ -632,26 +619,22 @@ static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint
"Failed to set blkio.weight_device: %m");
}
-static unsigned cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
+static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)];
char buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4];
CGroupIOLimitType type;
dev_t dev;
- unsigned n = 0;
int r;
r = lookup_block_device(dev_path, &dev);
if (r < 0)
- return 0;
+ return;
- for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) {
- if (limits[type] != cgroup_io_limit_defaults[type]) {
+ for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
+ if (limits[type] != cgroup_io_limit_defaults[type])
xsprintf(limit_bufs[type], "%" PRIu64, limits[type]);
- n++;
- } else {
+ else
xsprintf(limit_bufs[type], "%s", limits[type] == CGROUP_LIMIT_MAX ? "max" : "0");
- }
- }
xsprintf(buf, "%u:%u rbps=%s wbps=%s riops=%s wiops=%s\n", major(dev), minor(dev),
limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX],
@@ -660,36 +643,28 @@ static unsigned cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint
if (r < 0)
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set io.max: %m");
- return n;
}
-static unsigned cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) {
+static void cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) {
char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
dev_t dev;
- unsigned n = 0;
int r;
r = lookup_block_device(dev_path, &dev);
if (r < 0)
- return 0;
+ return;
- if (rbps != CGROUP_LIMIT_MAX)
- n++;
sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), rbps);
r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.read_bps_device", buf);
if (r < 0)
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set blkio.throttle.read_bps_device: %m");
- if (wbps != CGROUP_LIMIT_MAX)
- n++;
sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), wbps);
r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.write_bps_device", buf);
if (r < 0)
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set blkio.throttle.write_bps_device: %m");
-
- return n;
}
static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
@@ -840,16 +815,15 @@ static void cgroup_context_apply(
/* Apply limits and free ones without config. */
if (has_io) {
- CGroupIODeviceLimit *l, *next;
+ CGroupIODeviceLimit *l;
+
+ LIST_FOREACH(device_limits, l, c->io_device_limits)
+ cgroup_apply_io_device_limit(u, l->path, l->limits);
- LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
- if (!cgroup_apply_io_device_limit(u, l->path, l->limits))
- cgroup_context_free_io_device_limit(c, l);
- }
} else if (has_blockio) {
- CGroupBlockIODeviceBandwidth *b, *next;
+ CGroupBlockIODeviceBandwidth *b;
- LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths) {
+ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
CGroupIOLimitType type;
@@ -862,8 +836,7 @@ static void cgroup_context_apply(
log_cgroup_compat(u, "Applying BlockIO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as IO{Read|Write}BandwidthMax for %s",
b->rbps, b->wbps, b->path);
- if (!cgroup_apply_io_device_limit(u, b->path, limits))
- cgroup_context_free_blockio_device_bandwidth(c, b);
+ cgroup_apply_io_device_limit(u, b->path, limits);
}
}
}
@@ -917,21 +890,19 @@ static void cgroup_context_apply(
/* Apply limits and free ones without config. */
if (has_io) {
- CGroupIODeviceLimit *l, *next;
+ CGroupIODeviceLimit *l;
- LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
+ LIST_FOREACH(device_limits, l, c->io_device_limits) {
log_cgroup_compat(u, "Applying IO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as BlockIO{Read|Write}BandwidthMax for %s",
l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX], l->path);
- if (!cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]))
- cgroup_context_free_io_device_limit(c, l);
+ cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]);
}
} else if (has_blockio) {
- CGroupBlockIODeviceBandwidth *b, *next;
+ CGroupBlockIODeviceBandwidth *b;
- LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths)
- if (!cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps))
- cgroup_context_free_blockio_device_bandwidth(c, b);
+ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths)
+ cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps);
}
}
@@ -1318,7 +1289,7 @@ const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask) {
if (u->cgroup_path &&
u->cgroup_realized &&
- (u->cgroup_realized_mask & mask) == mask)
+ FLAGS_SET(u->cgroup_realized_mask, mask))
return u->cgroup_path;
u = UNIT_DEREF(u->slice);
@@ -1381,8 +1352,7 @@ int unit_set_cgroup_path(Unit *u, const char *path) {
unit_release_cgroup(u);
- u->cgroup_path = p;
- p = NULL;
+ u->cgroup_path = TAKE_PTR(p);
return 1;
}
@@ -1469,6 +1439,7 @@ static int unit_create_cgroup(
CGroupContext *c;
int r;
+ bool created;
assert(u);
@@ -1485,14 +1456,20 @@ static int unit_create_cgroup(
r = cg_create_everywhere(u->manager->cgroup_supported, target_mask, u->cgroup_path);
if (r < 0)
return log_unit_error_errno(u, r, "Failed to create cgroup %s: %m", u->cgroup_path);
+ created = !!r;
/* Start watching it */
(void) unit_watch_cgroup(u);
- /* Enable all controllers we need */
- r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path);
- if (r < 0)
- log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m", u->cgroup_path);
+ /* Preserve enabled controllers in delegated units, adjust others. */
+ if (created || !unit_cgroup_delegate(u)) {
+
+ /* Enable all controllers we need */
+ r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path);
+ if (r < 0)
+ log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m",
+ u->cgroup_path);
+ }
/* Keep track that this is now realized */
u->cgroup_realized = true;
@@ -1535,7 +1512,7 @@ static int unit_attach_pid_to_cgroup_via_bus(Unit *u, pid_t pid, const char *suf
return -EINVAL;
pp = strjoina("/", pp, suffix_path);
- path_kill_slashes(pp);
+ path_simplify(pp, false);
r = sd_bus_call_method(u->manager->system_bus,
"org.freedesktop.systemd1",
@@ -1706,7 +1683,6 @@ static void unit_remove_from_cgroup_realize_queue(Unit *u) {
u->in_cgroup_realize_queue = false;
}
-
/* Check if necessary controllers and attributes for a unit are in place.
*
* If so, do nothing.
@@ -2057,7 +2033,7 @@ static int on_cgroup_empty_event(sd_event_source *s, void *userdata) {
/* More stuff queued, let's make sure we remain enabled */
r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
if (r < 0)
- log_debug_errno(r, "Failed to reenable cgroup empty event source: %m");
+ log_debug_errno(r, "Failed to reenable cgroup empty event source, ignoring: %m");
}
unit_add_to_gc_queue(u);
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index ae5f1c7647..2d2ff6fc3c 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "cgroup-util.h"
@@ -140,7 +121,8 @@ typedef enum CGroupIPAccountingMetric {
_CGROUP_IP_ACCOUNTING_METRIC_INVALID = -1,
} CGroupIPAccountingMetric;
-#include "unit.h"
+typedef struct Unit Unit;
+typedef struct Manager Manager;
void cgroup_context_init(CGroupContext *c);
void cgroup_context_done(CGroupContext *c);
diff --git a/src/core/chown-recursive.c b/src/core/chown-recursive.c
index f021f03a06..c4794501c2 100644
--- a/src/core/chown-recursive.c
+++ b/src/core/chown-recursive.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
diff --git a/src/core/chown-recursive.h b/src/core/chown-recursive.h
index 7540a8db59..f3fa40a656 100644
--- a/src/core/chown-recursive.h
+++ b/src/core/chown-recursive.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/types.h>
int path_chown_recursive(const char *path, uid_t uid, gid_t gid);
diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c
index 113d352a43..bd6e6a9dde 100644
--- a/src/core/dbus-automount.c
+++ b/src/core/dbus-automount.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "automount.h"
#include "bus-util.h"
diff --git a/src/core/dbus-automount.h b/src/core/dbus-automount.h
index 378119410c..3e165b0566 100644
--- a/src/core/dbus-automount.h
+++ b/src/core/dbus-automount.h
@@ -1,25 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "sd-bus.h"
+#include "sd-bus-vtable.h"
+#include "unit.h"
extern const sd_bus_vtable bus_automount_vtable[];
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index 489112087f..540bc77aed 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <stdio_ext.h>
@@ -32,7 +14,6 @@
#include "fd-util.h"
#include "fileio.h"
#include "path-util.h"
-#include "unit.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
@@ -352,13 +333,13 @@ static int bus_cgroup_set_transient_property(
if (streq(name, "Delegate")) {
int b;
+ if (!UNIT_VTABLE(u)->can_delegate)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
+
r = sd_bus_message_read(message, "b", &b);
if (r < 0)
return r;
- if (!UNIT_VTABLE(u)->can_delegate && b)
- log_unit_notice(u, "Delegate=yes set, but has no effect for unit type");
-
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->delegate = b;
c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
@@ -371,6 +352,9 @@ static int bus_cgroup_set_transient_property(
} else if (streq(name, "DelegateControllers")) {
CGroupMask mask = 0;
+ if (!UNIT_VTABLE(u)->can_delegate)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
+
r = sd_bus_message_enter_container(message, 'a', "s");
if (r < 0)
return r;
@@ -412,9 +396,6 @@ static int bus_cgroup_set_transient_property(
unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
}
- if (!UNIT_VTABLE(u)->can_delegate && c->delegate)
- log_unit_notice(u, "Delegate=yes set, but has no effect for unit type");
-
return 1;
}
@@ -447,14 +428,129 @@ static int bus_cgroup_set_boolean(
return 1;
}
-static BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID,);
-static BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID,);
-static BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID,);
-static BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID,);
-static BUS_DEFINE_SET_CGROUP_WEIGHT(memory, CGROUP_MASK_MEMORY, , CGROUP_LIMIT_MAX, "infinity");
-static BUS_DEFINE_SET_CGROUP_WEIGHT(tasks_max, CGROUP_MASK_PIDS, , (uint64_t) -1, "infinity");
-static BUS_DEFINE_SET_CGROUP_SCALE(memory, CGROUP_MASK_MEMORY, physical_memory_scale);
-static BUS_DEFINE_SET_CGROUP_SCALE(tasks_max, CGROUP_MASK_PIDS, system_tasks_max_scale);
+#define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
+ static int bus_cgroup_set_##function( \
+ Unit *u, \
+ const char *name, \
+ uint64_t *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ uint64_t v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, "t", &v); \
+ if (r < 0) \
+ return r; \
+ \
+ if (!check(v)) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Value specified in %s is out of range", name); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = v; \
+ unit_invalidate_cgroup(u, (mask)); \
+ \
+ if (v == (val)) \
+ unit_write_settingf(u, flags, name, \
+ "%s=", name); \
+ else \
+ unit_write_settingf(u, flags, name, \
+ "%s=%" PRIu64, name, v); \
+ } \
+ \
+ return 1; \
+ }
+
+#define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
+ static int bus_cgroup_set_##function( \
+ Unit *u, \
+ const char *name, \
+ uint64_t *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ uint64_t v; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, "t", &v); \
+ if (r < 0) \
+ return r; \
+ \
+ if (v < minimum) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Value specified in %s is out of range", name); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ *p = v; \
+ unit_invalidate_cgroup(u, (mask)); \
+ \
+ if (v == CGROUP_LIMIT_MAX) \
+ unit_write_settingf(u, flags, name, \
+ "%s=infinity", name); \
+ else \
+ unit_write_settingf(u, flags, name, \
+ "%s=%" PRIu64, name, v); \
+ } \
+ \
+ return 1; \
+ } \
+ static int bus_cgroup_set_##function##_scale( \
+ Unit *u, \
+ const char *name, \
+ uint64_t *p, \
+ sd_bus_message *message, \
+ UnitWriteFlags flags, \
+ sd_bus_error *error) { \
+ \
+ uint64_t v; \
+ uint32_t raw; \
+ int r; \
+ \
+ assert(p); \
+ \
+ r = sd_bus_message_read(message, "u", &raw); \
+ if (r < 0) \
+ return r; \
+ \
+ v = scale(raw, UINT32_MAX); \
+ if (v < minimum || v >= UINT64_MAX) \
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
+ "Value specified in %s is out of range", name); \
+ \
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
+ const char *e; \
+ \
+ *p = v; \
+ unit_invalidate_cgroup(u, (mask)); \
+ \
+ /* Chop off suffix */ \
+ assert_se(e = endswith(name, "Scale")); \
+ name = strndupa(name, e - name); \
+ \
+ unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
+ (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
+ } \
+ \
+ return 1; \
+ }
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
+BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
+BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);
+BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
+BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
+BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
+BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
+BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max, CGROUP_MASK_PIDS, system_tasks_max_scale, 1);
+#pragma GCC diagnostic pop
int bus_cgroup_set_property(
Unit *u,
@@ -517,7 +613,7 @@ int bus_cgroup_set_property(
return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
if (streq(name, "MemorySwapMax"))
- return bus_cgroup_set_memory(u, name, &c->memory_swap_max, message, flags, error);
+ return bus_cgroup_set_swap(u, name, &c->memory_swap_max, message, flags, error);
if (streq(name, "MemoryMax"))
return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
@@ -532,7 +628,7 @@ int bus_cgroup_set_property(
return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
if (streq(name, "MemorySwapMaxScale"))
- return bus_cgroup_set_memory_scale(u, name, &c->memory_swap_max, message, flags, error);
+ return bus_cgroup_set_swap_scale(u, name, &c->memory_swap_max, message, flags, error);
if (streq(name, "MemoryMaxScale"))
return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
@@ -586,9 +682,8 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/"))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
+ if (!path_is_normalized(path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupIODeviceLimit *a = NULL, *b;
@@ -674,9 +769,8 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/"))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
+ if (!path_is_normalized(path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
@@ -760,9 +854,8 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/"))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
+ if (!path_is_normalized(path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupBlockIODeviceBandwidth *a = NULL, *b;
@@ -860,9 +953,8 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/"))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
+ if (!path_is_normalized(path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
@@ -962,15 +1054,12 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
- if ((!is_deviceallow_pattern(path) &&
- !path_startswith(path, "/run/systemd/inaccessible/")) ||
- strpbrk(path, WHITESPACE))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node");
+ if (!valid_device_allow_pattern(path) || strpbrk(path, WHITESPACE))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node or pattern");
if (isempty(rwm))
rwm = "rwm";
-
- if (!in_charset(rwm, "rwm"))
+ else if (!in_charset(rwm, "rwm"))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
diff --git a/src/core/dbus-cgroup.h b/src/core/dbus-cgroup.h
index 0588370aa5..188baa99e9 100644
--- a/src/core/dbus-cgroup.h
+++ b/src/core/dbus-cgroup.h
@@ -1,27 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
+#include "unit.h"
#include "cgroup.h"
extern const sd_bus_vtable bus_cgroup_vtable[];
diff --git a/src/core/dbus-device.c b/src/core/dbus-device.c
index fbb60d821e..6cf7f58e02 100644
--- a/src/core/dbus-device.c
+++ b/src/core/dbus-device.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "dbus-device.h"
#include "device.h"
diff --git a/src/core/dbus-device.h b/src/core/dbus-device.h
index c8098708f4..077a2bf128 100644
--- a/src/core/dbus-device.h
+++ b/src/core/dbus-device.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "unit.h"
+#include "sd-bus-vtable.h"
extern const sd_bus_vtable bus_device_vtable[];
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index c6c7f26773..c44970c10c 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/mount.h>
#include <sys/prctl.h>
@@ -64,13 +46,18 @@
BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
-
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode);
-
-static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
-static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_home, protect_home, ProtectHome);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, ProtectSystem);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long);
+static BUS_DEFINE_PROPERTY_GET(property_get_ioprio, "i", ExecContext, exec_context_get_effective_ioprio);
+static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_CLASS);
+static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_DATA);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
static int property_get_environment_files(
sd_bus *bus,
@@ -113,7 +100,6 @@ static int property_get_oom_score_adjust(
void *userdata,
sd_bus_error *error) {
-
ExecContext *c = userdata;
int32_t n;
@@ -143,7 +129,6 @@ static int property_get_nice(
void *userdata,
sd_bus_error *error) {
-
ExecContext *c = userdata;
int32_t n;
@@ -163,63 +148,6 @@ static int property_get_nice(
return sd_bus_message_append(reply, "i", n);
}
-static int property_get_ioprio(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", exec_context_get_effective_ioprio(c));
-}
-
-static int property_get_ioprio_class(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c)));
-}
-
-static int property_get_ioprio_priority(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c)));
-}
-
static int property_get_cpu_sched_policy(
sd_bus *bus,
const char *path,
@@ -292,10 +220,7 @@ static int property_get_cpu_affinity(
assert(reply);
assert(c);
- if (c->cpuset)
- return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
- else
- return sd_bus_message_append_array(reply, 'y', NULL, 0);
+ return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
}
static int property_get_timer_slack_nsec(
@@ -322,57 +247,6 @@ static int property_get_timer_slack_nsec(
return sd_bus_message_append(reply, "t", u);
}
-static int property_get_capability_bounding_set(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "t", c->capability_bounding_set);
-}
-
-static int property_get_ambient_capabilities(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "t", c->capability_ambient_set);
-}
-
-static int property_get_empty_string(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", "");
-}
-
static int property_get_syscall_filter(
sd_bus *bus,
const char *path,
@@ -425,10 +299,8 @@ static int property_get_syscall_filter(
if (r < 0)
return -ENOMEM;
}
- } else {
- s = name;
- name = NULL;
- }
+ } else
+ s = TAKE_PTR(name);
r = strv_consume(&l, s);
if (r < 0)
@@ -490,24 +362,6 @@ static int property_get_syscall_archs(
return 0;
}
-static int property_get_syscall_errno(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
-}
-
static int property_get_selinux_context(
sd_bus *bus,
const char *path,
@@ -562,24 +416,6 @@ static int property_get_smack_process_label(
return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
}
-static int property_get_personality(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
-}
-
static int property_get_address_families(
sd_bus *bus,
const char *path,
@@ -655,42 +491,6 @@ static int property_get_working_directory(
return sd_bus_message_append(reply, "s", wd);
}
-static int property_get_syslog_level(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
-}
-
-static int property_get_syslog_facility(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
-}
-
static int property_get_stdio_fdname(
sd_bus *bus,
const char *path,
@@ -758,7 +558,7 @@ static int property_get_bind_paths(
assert(property);
assert(reply);
- ro = !!strstr(property, "ReadOnly");
+ ro = strstr(property, "ReadOnly");
r = sd_bus_message_open_container(reply, 'a', "(ssbt)");
if (r < 0)
@@ -915,13 +715,13 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int, offsetof(ExecContext, log_level_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL, offsetof(ExecContext, capability_bounding_set), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("AmbientCapabilities", "t", NULL, offsetof(ExecContext, capability_ambient_set), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -939,8 +739,9 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("PrivateMounts", "b", bus_property_get_bool, offsetof(ExecContext, private_mounts), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -951,8 +752,8 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1126,12 +927,11 @@ int bus_set_transient_exec_command(
return -ENOMEM;
}
- c->argv = argv;
- argv = NULL;
+ c->argv = TAKE_PTR(argv);
c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
- path_kill_slashes(c->path);
+ path_simplify(c->path, false);
exec_command_append_list(exec_command, c);
}
@@ -1220,15 +1020,15 @@ static BUS_DEFINE_SET_TRANSIENT_IS_VALID(nice, "i", int32_t, int, "%" PRIi32, ni
static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string);
-static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, parse_protect_system_or_bool);
-static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, parse_protect_home_or_bool);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, protect_system_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, protect_home_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(sched_policy, "i", int32_t, int, "%" PRIi32, sched_policy_to_string_alloc_with_check);
-static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flag_to_string_many_with_check);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check);
int bus_exec_context_set_transient_property(
@@ -1239,8 +1039,8 @@ int bus_exec_context_set_transient_property(
UnitWriteFlags flags,
sd_bus_error *error) {
- const char *soft = NULL;
- int r, ri;
+ const char *suffix;
+ int r;
assert(u);
assert(c);
@@ -1306,6 +1106,9 @@ int bus_exec_context_set_transient_property(
if (streq(name, "PrivateDevices"))
return bus_set_transient_bool(u, name, &c->private_devices, message, flags, error);
+ if (streq(name, "PrivateMounts"))
+ return bus_set_transient_bool(u, name, &c->private_mounts, message, flags, error);
+
if (streq(name, "PrivateNetwork"))
return bus_set_transient_bool(u, name, &c->private_network, message, flags, error);
@@ -2044,9 +1847,7 @@ int bus_exec_context_set_transient_property(
if (!e)
return -ENOMEM;
- strv_free(c->environment);
- c->environment = e;
-
+ strv_free_and_replace(c->environment, e);
unit_write_settingf(u, flags, name, "Environment=%s", joined);
}
}
@@ -2080,9 +1881,7 @@ int bus_exec_context_set_transient_property(
if (!e)
return -ENOMEM;
- strv_free(c->unset_environment);
- c->unset_environment = e;
-
+ strv_free_and_replace(c->unset_environment, e);
unit_write_settingf(u, flags, name, "UnsetEnvironment=%s", joined);
}
}
@@ -2251,7 +2050,7 @@ int bus_exec_context_set_transient_property(
if (!path_is_absolute(i + offset))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
- path_kill_slashes(i + offset);
+ path_simplify(i + offset, false);
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
@@ -2291,8 +2090,14 @@ int bus_exec_context_set_transient_property(
return r;
STRV_FOREACH(p, l) {
- if (!path_is_normalized(*p) || path_is_absolute(*p))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not valid: %s", name, *p);
+ if (!path_is_normalized(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not normalized: %s", name, *p);
+
+ if (path_is_absolute(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is absolute: %s", name, *p);
+
+ if (path_startswith(*p, "private"))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path can't be 'private': %s", name, *p);
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
@@ -2465,73 +2270,77 @@ int bus_exec_context_set_transient_property(
}
return 1;
- }
- ri = rlimit_from_string(name);
- if (ri < 0) {
- soft = endswith(name, "Soft");
- if (soft) {
- const char *n;
+ } else if ((suffix = startswith(name, "Limit"))) {
+ const char *soft = NULL;
+ int ri;
- n = strndupa(name, soft - name);
- ri = rlimit_from_string(n);
- if (ri >= 0)
- name = n;
+ ri = rlimit_from_string(suffix);
+ if (ri < 0) {
+ soft = endswith(suffix, "Soft");
+ if (soft) {
+ const char *n;
+ n = strndupa(suffix, soft - suffix);
+ ri = rlimit_from_string(n);
+ if (ri >= 0)
+ name = strjoina("Limit", n);
+ }
}
- }
- if (ri >= 0) {
- uint64_t rl;
- rlim_t x;
+ if (ri >= 0) {
+ uint64_t rl;
+ rlim_t x;
- r = sd_bus_message_read(message, "t", &rl);
- if (r < 0)
- return r;
-
- if (rl == (uint64_t) -1)
- x = RLIM_INFINITY;
- else {
- x = (rlim_t) rl;
-
- if ((uint64_t) x != rl)
- return -ERANGE;
- }
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- _cleanup_free_ char *f = NULL;
- struct rlimit nl;
-
- if (c->rlimit[ri]) {
- nl = *c->rlimit[ri];
-
- if (soft)
- nl.rlim_cur = x;
- else
- nl.rlim_max = x;
- } else
- /* When the resource limit is not initialized yet, then assign the value to both fields */
- nl = (struct rlimit) {
- .rlim_cur = x,
- .rlim_max = x,
- };
-
- r = rlimit_format(&nl, &f);
+ r = sd_bus_message_read(message, "t", &rl);
if (r < 0)
return r;
- if (c->rlimit[ri])
- *c->rlimit[ri] = nl;
+ if (rl == (uint64_t) -1)
+ x = RLIM_INFINITY;
else {
- c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
- if (!c->rlimit[ri])
- return -ENOMEM;
+ x = (rlim_t) rl;
+
+ if ((uint64_t) x != rl)
+ return -ERANGE;
}
- unit_write_settingf(u, flags, name, "%s=%s", name, f);
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ _cleanup_free_ char *f = NULL;
+ struct rlimit nl;
+
+ if (c->rlimit[ri]) {
+ nl = *c->rlimit[ri];
+
+ if (soft)
+ nl.rlim_cur = x;
+ else
+ nl.rlim_max = x;
+ } else
+ /* When the resource limit is not initialized yet, then assign the value to both fields */
+ nl = (struct rlimit) {
+ .rlim_cur = x,
+ .rlim_max = x,
+ };
+
+ r = rlimit_format(&nl, &f);
+ if (r < 0)
+ return r;
+
+ if (c->rlimit[ri])
+ *c->rlimit[ri] = nl;
+ else {
+ c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
+ if (!c->rlimit[ri])
+ return -ENOMEM;
+ }
+
+ unit_write_settingf(u, flags, name, "%s=%s", name, f);
+ }
+
+ return 1;
}
- return 1;
}
return 0;
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
index 4d9b368f81..84051700ab 100644
--- a/src/core/dbus-execute.h
+++ b/src/core/dbus-execute.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "execute.h"
diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
index 0802fc9773..5551c56d0e 100644
--- a/src/core/dbus-job.c
+++ b/src/core/dbus-job.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-bus.h"
@@ -274,8 +256,7 @@ int bus_job_coldplug_bus_track(Job *j) {
assert(j);
- deserialized_clients = j->deserialized_clients;
- j->deserialized_clients = NULL;
+ deserialized_clients = TAKE_PTR(j->deserialized_clients);
if (strv_isempty(deserialized_clients))
return 0;
diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h
index 65d87814a6..3cc60f22ee 100644
--- a/src/core/dbus-job.h
+++ b/src/core/dbus-job.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "job.h"
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c
index 53d0aad63b..028e7ec1c1 100644
--- a/src/core/dbus-kill.c
+++ b/src/core/dbus-kill.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "bus-util.h"
#include "dbus-kill.h"
diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h
index 1df3b37c65..8192e94fbb 100644
--- a/src/core/dbus-kill.h
+++ b/src/core/dbus-kill.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "kill.h"
#include "unit.h"
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 889779d548..4ed68af1e0 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <sys/prctl.h>
@@ -39,6 +21,7 @@
#include "fs-util.h"
#include "install.h"
#include "log.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "selinux-access.h"
@@ -59,35 +42,14 @@ static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
(force ? UNIT_FILE_FORCE : 0);
}
-static int property_get_version(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
-}
-
-static int property_get_features(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
-}
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", PACKAGE_VERSION);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", SYSTEMD_FEATURES);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_architecture, "s", architecture_to_string(uname_architecture()));
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_log_target, "s", log_target_to_string(log_get_target()));
+static BUS_DEFINE_PROPERTY_GET2(property_get_system_state, "s", Manager, manager_state, manager_state_to_string);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_timer_slack_nsec, "t", (uint64_t) prctl(PR_GET_TIMERSLACK));
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "u", Hashmap *, hashmap_size);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_set_size, "u", Set *, set_size);
static int property_get_virtualization(
sd_bus *bus,
@@ -112,22 +74,7 @@ static int property_get_virtualization(
return sd_bus_message_append(
reply, "s",
- v == VIRTUALIZATION_NONE ? "" : virtualization_to_string(v));
-}
-
-static int property_get_architecture(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", architecture_to_string(uname_architecture()));
+ v == VIRTUALIZATION_NONE ? NULL : virtualization_to_string(v));
}
static int property_get_tainted(
@@ -153,21 +100,6 @@ static int property_get_tainted(
return sd_bus_message_append(reply, "s", s);
}
-static int property_get_log_target(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
-}
-
static int property_set_log_target(
sd_bus *bus,
const char *path,
@@ -177,6 +109,7 @@ static int property_set_log_target(
void *userdata,
sd_bus_error *error) {
+ Manager *m = userdata;
const char *t;
int r;
@@ -187,7 +120,19 @@ static int property_set_log_target(
if (r < 0)
return r;
- return log_set_target_from_string(t);
+ if (isempty(t))
+ manager_restore_original_log_target(m);
+ else {
+ LogTarget target;
+
+ target = log_target_from_string(t);
+ if (target < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log target '%s'", t);
+
+ manager_override_log_target(m, target);
+ }
+
+ return 0;
}
static int property_get_log_level(
@@ -221,6 +166,7 @@ static int property_set_log_level(
void *userdata,
sd_bus_error *error) {
+ Manager *m = userdata;
const char *t;
int r;
@@ -231,64 +177,19 @@ static int property_set_log_level(
if (r < 0)
return r;
- r = log_set_max_level_from_string(t);
- if (r == 0)
- log_info("Setting log level to %s.", t);
- return r;
-}
-
-static int property_get_n_names(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
-}
-
-static int property_get_n_failed_units(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "u", (uint32_t) set_size(m->failed_units));
-}
-
-static int property_get_n_jobs(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
+ if (isempty(t))
+ manager_restore_original_log_level(m);
+ else {
+ int level;
- Manager *m = userdata;
+ level = log_level_from_string(t);
+ if (level < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log level '%s'", t);
- assert(bus);
- assert(reply);
- assert(m);
+ manager_override_log_level(m, level);
+ }
- return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
+ return 0;
}
static int property_get_progress(
@@ -315,7 +216,7 @@ static int property_get_progress(
return sd_bus_message_append(reply, "d", d);
}
-static int property_get_system_state(
+static int property_get_show_status(
sd_bus *bus,
const char *path,
const char *interface,
@@ -325,12 +226,14 @@ static int property_get_system_state(
sd_bus_error *error) {
Manager *m = userdata;
+ int b;
assert(bus);
assert(reply);
assert(m);
- return sd_bus_message_append(reply, "s", manager_state_to_string(manager_state(m)));
+ b = m->show_status > 0;
+ return sd_bus_message_append_basic(reply, 'b', &b);
}
static int property_set_runtime_watchdog(
@@ -357,21 +260,6 @@ static int property_set_runtime_watchdog(
return watchdog_set_timeout(t);
}
-static int property_get_timer_slack_nsec(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "t", (uint64_t) prctl(PR_GET_TIMERSLACK));
-}
-
static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) {
Unit *u;
int r;
@@ -557,6 +445,32 @@ static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userd
return sd_bus_reply_method_return(message, "o", path);
}
+static int method_get_unit_by_control_group(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_free_ char *path = NULL;
+ Manager *m = userdata;
+ const char *cgroup;
+ Unit *u;
+ int r;
+
+ r = sd_bus_message_read(message, "s", &cgroup);
+ if (r < 0)
+ return r;
+
+ u = manager_get_unit_by_cgroup(m, cgroup);
+ if (!u)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Control group '%s' is not valid or not managed by this instance", cgroup);
+
+ r = mac_selinux_unit_access_check(u, message, "status", error);
+ if (r < 0)
+ return r;
+
+ path = unit_dbus_path(u);
+ if (!path)
+ return -ENOMEM;
+
+ return sd_bus_reply_method_return(message, "o", path);
+}
+
static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *path = NULL;
Manager *m = userdata;
@@ -714,7 +628,7 @@ static int method_set_unit_properties(sd_bus_message *message, void *userdata, s
if (r < 0)
return r;
- r = bus_unit_check_load_state(u, error);
+ r = bus_unit_validate_load_state(u, error);
if (r < 0)
return r;
@@ -738,7 +652,7 @@ static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error
if (r < 0)
return r;
- r = bus_unit_check_load_state(u, error);
+ r = bus_unit_validate_load_state(u, error);
if (r < 0)
return r;
@@ -762,7 +676,7 @@ static int method_unref_unit(sd_bus_message *message, void *userdata, sd_bus_err
if (r < 0)
return r;
- r = bus_unit_check_load_state(u, error);
+ r = bus_unit_validate_load_state(u, error);
if (r < 0)
return r;
@@ -1308,7 +1222,7 @@ static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_er
return sd_bus_reply_method_return(message, NULL);
}
-static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int dump_impl(sd_bus_message *message, void *userdata, sd_bus_error *error, int (*reply)(sd_bus_message *, char *)) {
_cleanup_free_ char *dump = NULL;
Manager *m = userdata;
int r;
@@ -1326,9 +1240,31 @@ static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *er
if (r < 0)
return r;
+ return reply(message, dump);
+}
+
+static int reply_dump(sd_bus_message *message, char *dump) {
return sd_bus_reply_method_return(message, "s", dump);
}
+static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return dump_impl(message, userdata, error, reply_dump);
+}
+
+static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
+ _cleanup_close_ int fd = -1;
+
+ fd = acquire_data_fd(dump, strlen(dump), 0);
+ if (fd < 0)
+ return fd;
+
+ return sd_bus_reply_method_return(message, "h", fd);
+}
+
+static int method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return dump_impl(message, userdata, error, reply_dump_by_fd);
+}
+
static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
}
@@ -1546,7 +1482,7 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
if (available < RELOAD_DISK_SPACE_MIN) {
char fb_available[FORMAT_BYTES_MAX], fb_need[FORMAT_BYTES_MAX];
- log_warning("Dangerously low amount of free space on /run/systemd, root switching operation might not complete successfuly. "
+ log_warning("Dangerously low amount of free space on /run/systemd, root switching operation might not complete successfully. "
"Currently, %s are free, but %s are suggested. Proceeding anyway.",
format_bytes(fb_available, sizeof(fb_available), available),
format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN));
@@ -1583,7 +1519,7 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
if (!path_is_absolute(init))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path to init binary '%s' not absolute.", init);
- r = chase_symlinks(init, root, CHASE_PREFIX_ROOT, &chased);
+ r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init);
@@ -1798,6 +1734,50 @@ static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *user
return sd_bus_reply_method_return(message, "s", name);
}
+static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ Manager *m = userdata;
+ DynamicUser *d;
+ Iterator i;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ assert_cc(sizeof(uid_t) == sizeof(uint32_t));
+
+ if (!MANAGER_IS_SYSTEM(m))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance.");
+
+ r = sd_bus_message_new_method_return(message, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "(us)");
+ if (r < 0)
+ return r;
+
+ HASHMAP_FOREACH(d, m->dynamic_users, i) {
+ uid_t uid;
+
+ r = dynamic_user_current(d, &uid);
+ if (r == -EAGAIN) /* not realized yet? */
+ continue;
+ if (r < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to lookup a dynamic user.");
+
+ r = sd_bus_message_append(reply, "(us)", uid, d->name);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
+
static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
@@ -1941,9 +1921,10 @@ static int install_error(
sd_bus_error *error,
int c,
UnitFileChange *changes,
- unsigned n_changes) {
+ size_t n_changes) {
+
+ size_t i;
int r;
- unsigned i;
for (i = 0; i < n_changes; i++)
@@ -1999,12 +1980,12 @@ static int reply_unit_file_changes_and_free(
sd_bus_message *message,
int carries_install_info,
UnitFileChange *changes,
- unsigned n_changes,
+ size_t n_changes,
sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
bool bad = false, good = false;
- unsigned i;
+ size_t i;
int r;
if (unit_file_changes_have_modification(changes, n_changes)) {
@@ -2065,13 +2046,13 @@ fail:
static int method_enable_unit_files_generic(
sd_bus_message *message,
Manager *m,
- int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
+ int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, size_t *n_changes),
bool carries_install_info,
sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
UnitFileFlags flags;
int runtime, force, r;
@@ -2113,7 +2094,7 @@ static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bu
return method_enable_unit_files_generic(message, userdata, unit_file_link, false, error);
}
-static int unit_file_preset_without_mode(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes) {
+static int unit_file_preset_without_mode(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, size_t *n_changes) {
return unit_file_preset(scope, flags, root_dir, files, UNIT_FILE_PRESET_FULL, changes, n_changes);
}
@@ -2129,7 +2110,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use
_cleanup_strv_free_ char **l = NULL;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
Manager *m = userdata;
UnitFilePresetMode mm;
int runtime, force, r;
@@ -2173,12 +2154,12 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use
static int method_disable_unit_files_generic(
sd_bus_message *message,
Manager *m,
- int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
+ int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, size_t *n_changes),
sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
int r, runtime;
assert(message);
@@ -2216,7 +2197,7 @@ static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_
static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
Manager *m = userdata;
int r;
@@ -2242,7 +2223,7 @@ static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_
static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
Manager *m = userdata;
const char *name;
int force, r;
@@ -2273,7 +2254,7 @@ static int method_set_default_target(sd_bus_message *message, void *userdata, sd
static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
Manager *m = userdata;
UnitFilePresetMode mm;
const char *mode;
@@ -2318,7 +2299,7 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd
_cleanup_strv_free_ char **l = NULL;
Manager *m = userdata;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
int runtime, force, r;
char *target, *type;
UnitDependency dep;
@@ -2357,7 +2338,7 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd
static int method_get_unit_file_links(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0, i;
+ size_t n_changes = 0, i;
UnitFileFlags flags;
const char *name;
char **p;
@@ -2439,15 +2420,15 @@ const sd_bus_vtable bus_manager_vtable[] = {
BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
- SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
- SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
+ SD_BUS_PROPERTY("NNames", "u", property_get_hashmap_size, offsetof(Manager, units), 0),
+ SD_BUS_PROPERTY("NFailedUnits", "u", property_get_set_size, offsetof(Manager, failed_units), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("NJobs", "u", property_get_hashmap_size, offsetof(Manager, jobs), 0),
SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ShowStatus", "b", property_get_show_status, 0, 0),
SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.search_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -2508,6 +2489,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUnitByInvocationID", "ay", "o", method_get_unit_by_invocation_id, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("GetUnitByControlGroup", "s", "o", method_get_unit_by_control_group, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2539,8 +2521,9 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("DumpByFileDescriptor", NULL, "h", method_dump_by_fd, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN),
SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
@@ -2572,6 +2555,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("LookupDynamicUserByName", "s", "u", method_lookup_dynamic_user_by_name, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("LookupDynamicUserByUID", "u", "s", method_lookup_dynamic_user_by_uid, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("GetDynamicUsers", NULL, "a(us)", method_get_dynamic_users, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("UnitNew", "so", 0),
SD_BUS_SIGNAL("UnitRemoved", "so", 0),
diff --git a/src/core/dbus-manager.h b/src/core/dbus-manager.h
index 1a6090f0f5..d0306adc70 100644
--- a/src/core/dbus-manager.h
+++ b/src/core/dbus-manager.h
@@ -1,24 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "sd-bus-vtable.h"
#include "manager.h"
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
index 9e52f55fa5..3f98d3ecf0 100644
--- a/src/core/dbus-mount.c
+++ b/src/core/dbus-mount.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "bus-util.h"
#include "dbus-cgroup.h"
@@ -28,78 +10,33 @@
#include "string-util.h"
#include "unit.h"
-static int property_get_what(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Mount *m = userdata;
- const char *d = NULL;
-
- assert(bus);
- assert(reply);
- assert(m);
-
+static const char *mount_get_what(const Mount *m) {
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what)
- d = m->parameters_proc_self_mountinfo.what;
- else if (m->from_fragment && m->parameters_fragment.what)
- d = m->parameters_fragment.what;
-
- return sd_bus_message_append(reply, "s", d);
+ return m->parameters_proc_self_mountinfo.what;
+ if (m->from_fragment && m->parameters_fragment.what)
+ return m->parameters_fragment.what;
+ return NULL;
}
-static int property_get_options(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Mount *m = userdata;
- const char *d = NULL;
-
- assert(bus);
- assert(reply);
- assert(m);
-
+static const char *mount_get_options(const Mount *m) {
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.options)
- d = m->parameters_proc_self_mountinfo.options;
- else if (m->from_fragment && m->parameters_fragment.options)
- d = m->parameters_fragment.options;
-
- return sd_bus_message_append(reply, "s", d);
+ return m->parameters_proc_self_mountinfo.options;
+ if (m->from_fragment && m->parameters_fragment.options)
+ return m->parameters_fragment.options;
+ return NULL;
}
-static int property_get_type(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- const char *fstype = NULL;
- Mount *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
+static const char *mount_get_fstype(const Mount *m) {
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
- fstype = m->parameters_proc_self_mountinfo.fstype;
+ return m->parameters_proc_self_mountinfo.fstype;
else if (m->from_fragment && m->parameters_fragment.fstype)
- fstype = m->parameters_fragment.fstype;
-
- return sd_bus_message_append(reply, "s", fstype);
+ return m->parameters_fragment.fstype;
+ return NULL;
}
+static BUS_DEFINE_PROPERTY_GET(property_get_what, "s", Mount, mount_get_what);
+static BUS_DEFINE_PROPERTY_GET(property_get_options, "s", Mount, mount_get_options);
+static BUS_DEFINE_PROPERTY_GET(property_get_type, "s", Mount, mount_get_fstype);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult);
const sd_bus_vtable bus_mount_vtable[] = {
@@ -115,8 +52,8 @@ const sd_bus_vtable bus_mount_vtable[] = {
SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ForceUnmount", "b", bus_property_get_bool, offsetof(Mount, force_unmount), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_VTABLE("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
diff --git a/src/core/dbus-mount.h b/src/core/dbus-mount.h
index 5d5e1f679f..f7112a9f02 100644
--- a/src/core/dbus-mount.h
+++ b/src/core/dbus-mount.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c
index b3f502f4c9..1a97d62486 100644
--- a/src/core/dbus-path.c
+++ b/src/core/dbus-path.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-util.h"
@@ -60,29 +42,9 @@ static int property_get_paths(
return sd_bus_message_close_container(reply);
}
-static int property_get_unit(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *p = userdata, *trigger;
-
- assert(bus);
- assert(reply);
- assert(p);
-
- trigger = UNIT_TRIGGER(p);
-
- return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
-}
-
const sd_bus_vtable bus_path_vtable[] = {
SD_BUS_VTABLE_START(0),
- SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Paths", "a(ss)", property_get_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MakeDirectory", "b", bus_property_get_bool, offsetof(Path, make_directory), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Path, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -141,13 +103,14 @@ static int bus_path_set_transient_property(
if (!k)
return -ENOMEM;
+ path_simplify(k, false);
+
s = new0(PathSpec, 1);
if (!s)
return -ENOMEM;
s->unit = u;
- s->path = path_kill_slashes(k);
- k = NULL;
+ s->path = TAKE_PTR(k);
s->type = t;
s->inotify_fd = -1;
diff --git a/src/core/dbus-path.h b/src/core/dbus-path.h
index ccd88c7f86..ad42b23662 100644
--- a/src/core/dbus-path.h
+++ b/src/core/dbus-path.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c
index 4d9ced81de..6725f62794 100644
--- a/src/core/dbus-scope.c
+++ b/src/core/dbus-scope.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-common-errors.h"
diff --git a/src/core/dbus-scope.h b/src/core/dbus-scope.h
index aa604897eb..7c080dbcf7 100644
--- a/src/core/dbus-scope.h
+++ b/src/core/dbus-scope.h
@@ -1,27 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
+#include "scope.h"
#include "unit.h"
extern const sd_bus_vtable bus_scope_vtable[];
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index 6de905b69c..1b4c98c7d2 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio_ext.h>
@@ -136,12 +118,12 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store), 0),
SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("StatusErrno", "i", bus_property_get_int, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -354,7 +336,8 @@ static int bus_service_set_transient_property(
if (streq(name, "SuccessExitStatus"))
return bus_set_transient_exit_status(u, name, &s->success_status, message, flags, error);
- if ((ci = service_exec_command_from_string(name)) >= 0)
+ ci = service_exec_command_from_string(name);
+ if (ci >= 0)
return bus_set_transient_exec_command(u, name, &s->exec_command[ci], message, flags, error);
if (streq(name, "StandardInputFileDescriptor"))
diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h
index 2da29ec601..22d2b887b4 100644
--- a/src/core/dbus-service.h
+++ b/src/core/dbus-service.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-slice.c b/src/core/dbus-slice.c
index fa2ff72151..722a5688a5 100644
--- a/src/core/dbus-slice.c
+++ b/src/core/dbus-slice.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "dbus-cgroup.h"
#include "dbus-slice.h"
diff --git a/src/core/dbus-slice.h b/src/core/dbus-slice.h
index 0c21919ad1..88cc48c808 100644
--- a/src/core/dbus-slice.h
+++ b/src/core/dbus-slice.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 035651f213..913cc74918 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-util.h"
@@ -36,6 +18,7 @@
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
+static BUS_DEFINE_PROPERTY_GET(property_get_fdname, "s", Socket, socket_fdname);
static int property_get_listen(
sd_bus *bus,
@@ -46,7 +29,6 @@ static int property_get_listen(
void *userdata,
sd_bus_error *error) {
-
Socket *s = SOCKET(userdata);
SocketPort *p;
int r;
@@ -92,25 +74,6 @@ static int property_get_listen(
return sd_bus_message_close_container(reply);
}
-
-static int property_get_fdname(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Socket *s = SOCKET(userdata);
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "s", socket_fdname(s));
-}
-
const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("BindIPv6Only", "s", property_get_bind_ipv6_only, offsetof(Socket, bind_ipv6_only), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -157,12 +120,13 @@ const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("NConnections", "u", bus_property_get_unsigned, offsetof(Socket, n_connections), 0),
SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), 0),
+ SD_BUS_PROPERTY("NRefused", "u", bus_property_get_unsigned, offsetof(Socket, n_refused), 0),
SD_BUS_PROPERTY("FileDescriptorName", "s", property_get_fdname, 0, 0),
SD_BUS_PROPERTY("SocketProtocol", "i", bus_property_get_int, offsetof(Socket, socket_protocol), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TriggerLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Socket, trigger_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TriggerLimitBurst", "u", bus_property_get_unsigned, offsetof(Socket, trigger_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
@@ -174,7 +138,10 @@ static inline bool check_size_t_truncation(uint64_t t) {
return (size_t) t == t;
}
-static inline const char* socket_protocol_to_name_supported(int32_t i) {
+static inline const char* supported_socket_protocol_to_string(int32_t i) {
+ if (i == IPPROTO_IP)
+ return "";
+
if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
return NULL;
@@ -184,11 +151,11 @@ static inline const char* socket_protocol_to_name_supported(int32_t i) {
static BUS_DEFINE_SET_TRANSIENT(int, "i", int32_t, int, "%" PRIi32);
static BUS_DEFINE_SET_TRANSIENT(message_queue, "x", int64_t, long, "%" PRIi64);
static BUS_DEFINE_SET_TRANSIENT_IS_VALID(size_t_check_truncation, "t", uint64_t, size_t, "%" PRIu64, check_size_t_truncation);
-static BUS_DEFINE_SET_TRANSIENT_PARSE(bind_ipv6_only, SocketAddressBindIPv6Only, parse_socket_address_bind_ipv6_only_or_bool);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(bind_ipv6_only, SocketAddressBindIPv6Only, socket_address_bind_ipv6_only_or_bool_from_string);
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(fdname, fdname_is_valid);
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(ifname, ifname_valid);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(ip_tos, "i", int32_t, int, "%" PRIi32, ip_tos_to_string_alloc);
-static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, socket_protocol_to_name_supported);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, supported_socket_protocol_to_string);
static int bus_socket_set_transient_property(
Socket *s,
@@ -394,7 +361,7 @@ static int bus_socket_set_transient_property(
if (p->type != SOCKET_SOCKET) {
p->path = strdup(a);
- path_kill_slashes(p->path);
+ path_simplify(p->path, false);
} else if (streq(t, "Netlink")) {
r = socket_address_parse_netlink(&p->address, a);
diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h
index e6db2d0772..9aa8133d18 100644
--- a/src/core/dbus-socket.h
+++ b/src/core/dbus-socket.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c
index 795aaa94fe..b272d10113 100644
--- a/src/core/dbus-swap.c
+++ b/src/core/dbus-swap.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Maarten Lankhorst
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 Maarten Lankhorst
***/
#include "bus-util.h"
@@ -27,54 +11,22 @@
#include "swap.h"
#include "unit.h"
-static int property_get_priority(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Swap *s = SWAP(userdata);
- int p;
-
- assert(bus);
- assert(reply);
- assert(s);
-
+static int swap_get_priority(Swap *s) {
if (s->from_proc_swaps)
- p = s->parameters_proc_swaps.priority;
- else if (s->from_fragment)
- p = s->parameters_fragment.priority;
- else
- p = -1;
-
- return sd_bus_message_append(reply, "i", p);
+ return s->parameters_proc_swaps.priority;
+ if (s->from_fragment)
+ return s->parameters_fragment.priority;
+ return -1;
}
-static int property_get_options(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Swap *s = SWAP(userdata);
- const char *options = NULL;
-
- assert(bus);
- assert(reply);
- assert(s);
-
+static const char *swap_get_options(Swap *s) {
if (s->from_fragment)
- options = s->parameters_fragment.options;
-
- return sd_bus_message_append(reply, "s", options);
+ return s->parameters_fragment.options;
+ return NULL;
}
+static BUS_DEFINE_PROPERTY_GET(property_get_priority, "i", Swap, swap_get_priority);
+static BUS_DEFINE_PROPERTY_GET(property_get_options, "s", Swap, swap_get_options);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, swap_result, SwapResult);
const sd_bus_vtable bus_swap_vtable[] = {
@@ -85,8 +37,8 @@ const sd_bus_vtable bus_swap_vtable[] = {
SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_COMMAND_VTABLE("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_VTABLE("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_VTABLE_END
diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h
index 6cca7483d8..b114fe04c7 100644
--- a/src/core/dbus-swap.h
+++ b/src/core/dbus-swap.h
@@ -2,26 +2,11 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Maarten Lankhorst
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 Maarten Lankhorst
***/
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-target.c b/src/core/dbus-target.c
index 7060b65c6e..ba50113641 100644
--- a/src/core/dbus-target.c
+++ b/src/core/dbus-target.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "dbus-target.h"
#include "unit.h"
diff --git a/src/core/dbus-target.h b/src/core/dbus-target.h
index 7852917962..ad02a1db74 100644
--- a/src/core/dbus-target.h
+++ b/src/core/dbus-target.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
+#include "sd-bus-vtable.h"
extern const sd_bus_vtable bus_target_vtable[];
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index 1eedf217fe..b9d2f3d07e 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-util.h"
@@ -116,26 +98,6 @@ static int property_get_calendar_timers(
return sd_bus_message_close_container(reply);
}
-static int property_get_unit(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata, *trigger;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- trigger = UNIT_TRIGGER(u);
-
- return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
-}
-
static int property_get_next_elapse_monotonic(
sd_bus *bus,
const char *path,
@@ -158,7 +120,7 @@ static int property_get_next_elapse_monotonic(
const sd_bus_vtable bus_timer_vtable[] = {
SD_BUS_VTABLE_START(0),
- SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -290,8 +252,7 @@ static int bus_timer_set_transient_property(
return -ENOMEM;
v->base = b;
- v->calendar_spec = c;
- c = NULL;
+ v->calendar_spec = TAKE_PTR(c);
LIST_PREPEND(value, t->values, v);
}
@@ -377,8 +338,7 @@ static int bus_timer_set_transient_property(
return -ENOMEM;
v->base = TIMER_CALENDAR;
- v->calendar_spec = c;
- c = NULL;
+ v->calendar_spec = TAKE_PTR(c);
LIST_PREPEND(value, t->values, v);
}
diff --git a/src/core/dbus-timer.h b/src/core/dbus-timer.h
index d810b048ee..bb126b22dc 100644
--- a/src/core/dbus-timer.h
+++ b/src/core/dbus-timer.h
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
#include "unit.h"
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 50a5ab9819..ae0410414e 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-bus.h"
@@ -42,10 +24,32 @@
#include "user-util.h"
#include "web-util.h"
+static bool unit_can_start_refuse_manual(Unit *u) {
+ return unit_can_start(u) && !u->refuse_manual_start;
+}
+
+static bool unit_can_stop_refuse_manual(Unit *u) {
+ return unit_can_stop(u) && !u->refuse_manual_stop;
+}
+
+static bool unit_can_isolate_refuse_manual(Unit *u) {
+ return unit_can_isolate(u) && !u->refuse_manual_start;
+}
+
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
+static BUS_DEFINE_PROPERTY_GET(property_get_description, "s", Unit, unit_description);
+static BUS_DEFINE_PROPERTY_GET2(property_get_active_state, "s", Unit, unit_active_state, unit_active_state_to_string);
+static BUS_DEFINE_PROPERTY_GET(property_get_sub_state, "s", Unit, unit_sub_state_to_string);
+static BUS_DEFINE_PROPERTY_GET2(property_get_unit_file_state, "s", Unit, unit_get_unit_file_state, unit_file_state_to_string);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_reload, "b", Unit, unit_can_reload);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_start, "b", Unit, unit_can_start_refuse_manual);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_stop, "b", Unit, unit_can_stop_refuse_manual);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_isolate, "b", Unit, unit_can_isolate_refuse_manual);
+static BUS_DEFINE_PROPERTY_GET(property_get_need_daemon_reload, "b", Unit, unit_need_daemon_reload);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_strv, "as", 0);
static int property_get_names(
sd_bus *bus,
@@ -56,20 +60,20 @@ static int property_get_names(
void *userdata,
sd_bus_error *error) {
- Unit *u = userdata;
+ Set **s = userdata;
Iterator i;
const char *t;
int r;
assert(bus);
assert(reply);
- assert(u);
+ assert(s);
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
- SET_FOREACH(t, u->names, i) {
+ SET_FOREACH(t, *s, i) {
r = sd_bus_message_append(reply, "s", t);
if (r < 0)
return r;
@@ -94,7 +98,7 @@ static int property_get_following(
assert(u);
f = unit_following(u);
- return sd_bus_message_append(reply, "s", f ? f->id : "");
+ return sd_bus_message_append(reply, "s", f ? f->id : NULL);
}
static int property_get_dependencies(
@@ -106,7 +110,7 @@ static int property_get_dependencies(
void *userdata,
sd_bus_error *error) {
- Hashmap *h = *(Hashmap**) userdata;
+ Hashmap **h = userdata;
Iterator j;
Unit *u;
void *v;
@@ -114,12 +118,13 @@ static int property_get_dependencies(
assert(bus);
assert(reply);
+ assert(h);
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
- HASHMAP_FOREACH_KEY(v, u, h, j) {
+ HASHMAP_FOREACH_KEY(v, u, *h, j) {
r = sd_bus_message_append(reply, "s", u->id);
if (r < 0)
return r;
@@ -128,22 +133,6 @@ static int property_get_dependencies(
return sd_bus_message_close_container(reply);
}
-static int property_get_obsolete_dependencies(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- /* For dependency types we don't support anymore always return an empty array */
- return sd_bus_message_append(reply, "as", 0);
-}
-
static int property_get_requires_mounts_for(
sd_bus *bus,
const char *path,
@@ -153,7 +142,7 @@ static int property_get_requires_mounts_for(
void *userdata,
sd_bus_error *error) {
- Hashmap *h = *(Hashmap**) userdata;
+ Hashmap **h = userdata;
const char *p;
Iterator j;
void *v;
@@ -161,12 +150,13 @@ static int property_get_requires_mounts_for(
assert(bus);
assert(reply);
+ assert(h);
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
- HASHMAP_FOREACH_KEY(v, p, h, j) {
+ HASHMAP_FOREACH_KEY(v, p, *h, j) {
r = sd_bus_message_append(reply, "s", p);
if (r < 0)
return r;
@@ -175,60 +165,6 @@ static int property_get_requires_mounts_for(
return sd_bus_message_close_container(reply);
}
-static int property_get_description(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", unit_description(u));
-}
-
-static int property_get_active_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
-}
-
-static int property_get_sub_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
-}
-
static int property_get_unit_file_preset(
sd_bus *bus,
const char *path,
@@ -248,100 +184,10 @@ static int property_get_unit_file_preset(
r = unit_get_unit_file_preset(u);
return sd_bus_message_append(reply, "s",
- r < 0 ? "":
+ r < 0 ? NULL:
r > 0 ? "enabled" : "disabled");
}
-static int property_get_unit_file_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
-}
-
-static int property_get_can_start(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
-}
-
-static int property_get_can_stop(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_can_stop(u) && !u->refuse_manual_stop);
-}
-
-static int property_get_can_reload(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_can_reload(u));
-}
-
-static int property_get_can_isolate(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
-}
-
static int property_get_job(
sd_bus *bus,
const char *path,
@@ -352,38 +198,20 @@ static int property_get_job(
sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
- Unit *u = userdata;
+ Job **j = userdata;
assert(bus);
assert(reply);
- assert(u);
+ assert(j);
- if (!u->job)
+ if (!*j)
return sd_bus_message_append(reply, "(uo)", 0, "/");
- p = job_dbus_path(u->job);
+ p = job_dbus_path(*j);
if (!p)
return -ENOMEM;
- return sd_bus_message_append(reply, "(uo)", u->job->id, p);
-}
-
-static int property_get_need_daemon_reload(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
+ return sd_bus_message_append(reply, "(uo)", (*j)->id, p);
}
static int property_get_conditions(
@@ -439,15 +267,17 @@ static int property_get_load_error(
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
Unit *u = userdata;
+ int r;
assert(bus);
assert(reply);
assert(u);
- if (u->load_error != 0)
- sd_bus_error_set_errno(&e, u->load_error);
+ r = bus_unit_validate_load_state(u, &e);
+ if (r < 0)
+ return sd_bus_message_append(reply, "(ss)", e.name, e.message);
- return sd_bus_message_append(reply, "(ss)", e.name, e.message);
+ return sd_bus_message_append(reply, "(ss)", NULL, NULL);
}
static int bus_verify_manage_units_async_full(
@@ -735,7 +565,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Names", "as", property_get_names, offsetof(Unit, names), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -777,7 +607,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("Job", "(uo)", property_get_job, offsetof(Unit, job), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -821,11 +651,12 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED),
- /* Obsolete properties or obsolete alias names */
- SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
- SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
- SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
- SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
+ /* For dependency types we don't support anymore always return an empty array */
+ SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
+ /* Obsolete alias names */
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_VTABLE_END
@@ -931,7 +762,7 @@ static int property_get_cgroup(
sd_bus_error *error) {
Unit *u = userdata;
- const char *t;
+ const char *t = NULL;
assert(bus);
assert(reply);
@@ -944,9 +775,7 @@ static int property_get_cgroup(
* other cases we report as-is. */
if (u->cgroup_path)
- t = isempty(u->cgroup_path) ? "/" : u->cgroup_path;
- else
- t = "";
+ t = empty_to_root(u->cgroup_path);
return sd_bus_message_append(reply, "s", t);
}
@@ -992,7 +821,7 @@ static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
assert(p);
r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f);
- if (r == ENOENT)
+ if (r == -ENOENT)
return 0;
if (r < 0)
return r;
@@ -1043,7 +872,7 @@ static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(set_freep) Set *pids = NULL;
+ _cleanup_set_free_ Set *pids = NULL;
Unit *u = userdata;
pid_t pid;
int r;
@@ -1130,7 +959,7 @@ static int property_get_ip_counter(
int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- _cleanup_(set_freep) Set *pids = NULL;
+ _cleanup_set_free_ Set *pids = NULL;
Unit *u = userdata;
const char *path;
int r;
@@ -1408,7 +1237,7 @@ int bus_unit_queue_job(
}
if (type == JOB_STOP &&
- (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR)) &&
+ IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) &&
unit_active_state(u) == UNIT_INACTIVE)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
@@ -1880,22 +1709,33 @@ int bus_unit_set_properties(
return n;
}
-int bus_unit_check_load_state(Unit *u, sd_bus_error *error) {
+int bus_unit_validate_load_state(Unit *u, sd_bus_error *error) {
assert(u);
- if (u->load_state == UNIT_LOADED)
- return 0;
+ /* Generates a pretty error if a unit isn't properly loaded. */
- /* Give a better description of the unit error when
- * possible. Note that in the case of UNIT_MASKED, load_error
- * is not set. */
- if (u->load_state == UNIT_MASKED)
- return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
+ switch (u->load_state) {
+
+ case UNIT_LOADED:
+ return 0;
- if (u->load_state == UNIT_NOT_FOUND)
+ case UNIT_NOT_FOUND:
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id);
- return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id);
+ case UNIT_BAD_SETTING:
+ return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Unit %s has a bad unit file setting.", u->id);
+
+ case UNIT_ERROR: /* Only show .load_error in UNIT_ERROR state */
+ return sd_bus_error_set_errnof(error, u->load_error, "Unit %s failed to loaded properly: %m.", u->id);
+
+ case UNIT_MASKED:
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
+
+ case UNIT_STUB:
+ case UNIT_MERGED:
+ default:
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unexpected load state of unit %s", u->id);
+ }
}
static int bus_unit_track_handler(sd_bus_track *t, void *userdata) {
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index bb4e43f5ca..68eb621836 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -1,27 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+#include "sd-bus-vtable.h"
+#include "job.h"
#include "unit.h"
extern const sd_bus_vtable bus_unit_vtable[];
@@ -42,7 +25,7 @@ int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *e
int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error);
-int bus_unit_check_load_state(Unit *u, sd_bus_error *error);
+int bus_unit_validate_load_state(Unit *u, sd_bus_error *error);
int bus_unit_track_add_name(Unit *u, const char *name);
int bus_unit_track_add_sender(Unit *u, sd_bus_message *m);
diff --git a/src/core/dbus-util.c b/src/core/dbus-util.c
index 75bbd07604..f4fbb72cb9 100644
--- a/src/core/dbus-util.c
+++ b/src/core/dbus-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "bus-util.h"
#include "dbus-util.h"
@@ -26,6 +8,26 @@
#include "user-util.h"
#include "unit.h"
+int bus_property_get_triggered_unit(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Unit *u = userdata, *trigger;
+
+ assert(bus);
+ assert(reply);
+ assert(u);
+
+ trigger = UNIT_TRIGGER(u);
+
+ return sd_bus_message_append(reply, "s", trigger ? trigger->id : NULL);
+}
+
BUS_DEFINE_SET_TRANSIENT(mode_t, "u", uint32_t, mode_t, "%040o");
BUS_DEFINE_SET_TRANSIENT(unsigned, "u", uint32_t, unsigned, "%" PRIu32);
BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user, valid_user_group_name_or_id);
diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h
index 8260298577..12b055e4ac 100644
--- a/src/core/dbus-util.h
+++ b/src/core/dbus-util.h
@@ -1,28 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
+
#include "unit.h"
+int bus_property_get_triggered_unit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+
#define BUS_DEFINE_SET_TRANSIENT(function, bus_type, type, cast_type, fmt) \
int bus_set_transient_##function( \
Unit *u, \
@@ -48,8 +32,7 @@
} \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#define BUS_DEFINE_SET_TRANSIENT_IS_VALID(function, bus_type, type, cast_type, fmt, check) \
int bus_set_transient_##function( \
@@ -80,8 +63,7 @@
} \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#define BUS_DEFINE_SET_TRANSIENT_TO_STRING(function, bus_type, type, cast_type, fmt, to_string) \
int bus_set_transient_##function( \
@@ -114,8 +96,7 @@
} \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#define BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(function, bus_type, type, cast_type, fmt, to_string) \
int bus_set_transient_##function( \
@@ -150,8 +131,7 @@
} \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#define BUS_DEFINE_SET_TRANSIENT_PARSE(function, type, parse) \
int bus_set_transient_##function( \
@@ -184,8 +164,7 @@
} \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#define BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(function, type, parse) \
int bus_set_transient_##function( \
@@ -218,8 +197,7 @@
} \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#define BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(function, check) \
int bus_set_transient_##function( \
@@ -253,88 +231,7 @@
} \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-#define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val, str) \
- int bus_cgroup_set_##function( \
- Unit *u, \
- const char *name, \
- uint64_t *p, \
- sd_bus_message *message, \
- UnitWriteFlags flags, \
- sd_bus_error *error) { \
- \
- uint64_t v; \
- int r; \
- \
- assert(p); \
- \
- r = sd_bus_message_read(message, "t", &v); \
- if (r < 0) \
- return r; \
- \
- if (!check(v)) \
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
- "Value specified in %s is out of range", name); \
- \
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
- *p = v; \
- unit_invalidate_cgroup(u, (mask)); \
- \
- if (v == (val)) \
- unit_write_settingf(u, flags, name, \
- "%s=" str, name); \
- else \
- unit_write_settingf(u, flags, name, \
- "%s=%" PRIu64, name, v); \
- } \
- \
- return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-#define BUS_DEFINE_SET_CGROUP_SCALE(function, mask, scale) \
- int bus_cgroup_set_##function##_scale( \
- Unit *u, \
- const char *name, \
- uint64_t *p, \
- sd_bus_message *message, \
- UnitWriteFlags flags, \
- sd_bus_error *error) { \
- \
- uint64_t v; \
- uint32_t raw; \
- int r; \
- \
- assert(p); \
- \
- r = sd_bus_message_read(message, "u", &raw); \
- if (r < 0) \
- return r; \
- \
- v = scale(raw, UINT32_MAX); \
- if (v <= 0 || v >= UINT64_MAX) \
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
- "Value specified in %s is out of range", name); \
- \
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
- const char *e; \
- \
- *p = v; \
- unit_invalidate_cgroup(u, (mask)); \
- \
- /* Chop off suffix */ \
- assert_se(e = endswith(name, "Scale")); \
- name = strndupa(name, e - name); \
- \
- unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
- (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
- } \
- \
- return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
int bus_set_transient_mode_t(Unit *u, const char *name, mode_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_unsigned(Unit *u, const char *name, unsigned *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 56b43adcda..bf5917696e 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <sys/epoll.h>
@@ -29,11 +11,22 @@
#include "bus-error.h"
#include "bus-internal.h"
#include "bus-util.h"
+#include "dbus-automount.h"
#include "dbus-cgroup.h"
+#include "dbus-device.h"
#include "dbus-execute.h"
#include "dbus-job.h"
#include "dbus-kill.h"
#include "dbus-manager.h"
+#include "dbus-mount.h"
+#include "dbus-path.h"
+#include "dbus-scope.h"
+#include "dbus-service.h"
+#include "dbus-slice.h"
+#include "dbus-socket.h"
+#include "dbus-swap.h"
+#include "dbus-target.h"
+#include "dbus-timer.h"
#include "dbus-unit.h"
#include "dbus.h"
#include "fd-util.h"
@@ -43,6 +36,7 @@
#include "mkdir.h"
#include "process-util.h"
#include "selinux-access.h"
+#include "service.h"
#include "special.h"
#include "string-util.h"
#include "strv.h"
@@ -242,7 +236,6 @@ static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_er
path = sd_bus_message_get_path(message);
if (object_path_startswith("/org/freedesktop/systemd1", path)) {
-
r = mac_selinux_access_check(message, verb, error);
if (r < 0)
return r;
@@ -270,7 +263,6 @@ static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_er
else
manager_load_unit_from_dbus_path(m, path, NULL, &u);
}
-
if (!u)
return 0;
@@ -501,8 +493,7 @@ static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char
assert(hashmap_size(m->jobs) == k);
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return k;
}
@@ -526,8 +517,7 @@ static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, cha
k++;
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return k;
}
@@ -897,9 +887,9 @@ int bus_init_api(Manager *m) {
bus = sd_bus_ref(m->system_bus);
else {
if (MANAGER_IS_SYSTEM(m))
- r = sd_bus_open_system(&bus);
+ r = sd_bus_open_system_with_description(&bus, "bus-api-system");
else
- r = sd_bus_open_user(&bus);
+ r = sd_bus_open_user_with_description(&bus, "bus-api-user");
if (r < 0)
return log_error_errno(r, "Failed to connect to API bus: %m");
@@ -916,8 +906,7 @@ int bus_init_api(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to set up API bus: %m");
- m->api_bus = bus;
- bus = NULL;
+ m->api_bus = TAKE_PTR(bus);
r = manager_enqueue_sync_bus_names(m);
if (r < 0)
@@ -961,7 +950,7 @@ int bus_init_system(Manager *m) {
if (MANAGER_IS_SYSTEM(m) && m->api_bus)
bus = sd_bus_ref(m->api_bus);
else {
- r = sd_bus_open_system(&bus);
+ r = sd_bus_open_system_with_description(&bus, "bus-system");
if (r < 0)
return log_error_errno(r, "Failed to connect to system bus: %m");
@@ -978,8 +967,7 @@ int bus_init_system(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to set up system bus: %m");
- m->system_bus = bus;
- bus = NULL;
+ m->system_bus = TAKE_PTR(bus);
return 0;
}
@@ -1105,17 +1093,11 @@ static void destroy_bus(Manager *m, sd_bus **bus) {
}
void bus_done_api(Manager *m) {
- assert(m);
-
- if (m->api_bus)
- destroy_bus(m, &m->api_bus);
+ destroy_bus(m, &m->api_bus);
}
void bus_done_system(Manager *m) {
- assert(m);
-
- if (m->system_bus)
- destroy_bus(m, &m->system_bus);
+ destroy_bus(m, &m->system_bus);
}
void bus_done_private(Manager *m) {
@@ -1310,3 +1292,38 @@ uint64_t manager_bus_n_queued_write(Manager *m) {
return c;
}
+
+static void vtable_dump_bus_properties(FILE *f, const sd_bus_vtable *table) {
+ const sd_bus_vtable *i;
+
+ for (i = table; i->type != _SD_BUS_VTABLE_END; i++) {
+ if (!IN_SET(i->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY) ||
+ (i->flags & (SD_BUS_VTABLE_DEPRECATED | SD_BUS_VTABLE_HIDDEN)) != 0)
+ continue;
+
+ fprintf(f, "%s\n", i->x.property.member);
+ }
+}
+
+void dump_bus_properties(FILE *f) {
+ assert(f);
+
+ vtable_dump_bus_properties(f, bus_automount_vtable);
+ vtable_dump_bus_properties(f, bus_cgroup_vtable);
+ vtable_dump_bus_properties(f, bus_device_vtable);
+ vtable_dump_bus_properties(f, bus_exec_vtable);
+ vtable_dump_bus_properties(f, bus_job_vtable);
+ vtable_dump_bus_properties(f, bus_kill_vtable);
+ vtable_dump_bus_properties(f, bus_manager_vtable);
+ vtable_dump_bus_properties(f, bus_mount_vtable);
+ vtable_dump_bus_properties(f, bus_path_vtable);
+ vtable_dump_bus_properties(f, bus_scope_vtable);
+ vtable_dump_bus_properties(f, bus_service_vtable);
+ vtable_dump_bus_properties(f, bus_slice_vtable);
+ vtable_dump_bus_properties(f, bus_socket_vtable);
+ vtable_dump_bus_properties(f, bus_swap_vtable);
+ vtable_dump_bus_properties(f, bus_target_vtable);
+ vtable_dump_bus_properties(f, bus_timer_vtable);
+ vtable_dump_bus_properties(f, bus_unit_vtable);
+ vtable_dump_bus_properties(f, bus_unit_cgroup_vtable);
+}
diff --git a/src/core/dbus.h b/src/core/dbus.h
index 702bc48ae1..382a96da7d 100644
--- a/src/core/dbus.h
+++ b/src/core/dbus.h
@@ -1,24 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "sd-bus.h"
#include "manager.h"
@@ -50,3 +33,5 @@ int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_er
int bus_forward_agent_released(Manager *m, const char *path);
uint64_t manager_bus_n_queued_write(Manager *m);
+
+void dump_bus_properties(FILE *f);
diff --git a/src/core/device.c b/src/core/device.c
index a57c34ddf1..a2d00a0fbe 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <sys/epoll.h>
@@ -24,6 +6,7 @@
#include "libudev.h"
#include "alloc-util.h"
+#include "bus-error.h"
#include "dbus-device.h"
#include "device.h"
#include "log.h"
@@ -43,6 +26,7 @@ static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
};
static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask);
static void device_unset_sysfs(Device *d) {
Hashmap *devices;
@@ -68,8 +52,8 @@ static void device_unset_sysfs(Device *d) {
}
static int device_set_sysfs(Device *d, const char *sysfs) {
+ _cleanup_free_ char *copy = NULL;
Device *first;
- char *copy;
int r;
assert(d);
@@ -93,12 +77,10 @@ static int device_set_sysfs(Device *d, const char *sysfs) {
r = hashmap_replace(UNIT(d)->manager->devices_by_sysfs, copy, first);
if (r < 0) {
LIST_REMOVE(same_sysfs, first, d);
- free(copy);
return r;
}
- d->sysfs = copy;
-
+ d->sysfs = TAKE_PTR(copy);
return 0;
}
@@ -116,6 +98,8 @@ static void device_init(Unit *u) {
u->job_running_timeout = u->manager->default_timeout_start_usec;
u->ignore_on_isolate = true;
+
+ d->deserialized_state = _DEVICE_STATE_INVALID;
}
static void device_done(Unit *u) {
@@ -124,6 +108,7 @@ static void device_done(Unit *u) {
assert(d);
device_unset_sysfs(d);
+ d->wants_property = strv_free(d->wants_property);
}
static void device_set_state(Device *d, DeviceState state) {
@@ -133,10 +118,13 @@ static void device_set_state(Device *d, DeviceState state) {
old_state = d->state;
d->state = state;
+ if (state == DEVICE_DEAD)
+ device_unset_sysfs(d);
+
if (state != old_state)
log_unit_debug(UNIT(d), "Changed %s -> %s", device_state_to_string(old_state), device_state_to_string(state));
- unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
+ unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], 0);
}
static int device_coldplug(Unit *u) {
@@ -145,19 +133,93 @@ static int device_coldplug(Unit *u) {
assert(d);
assert(d->state == DEVICE_DEAD);
- if (d->found & DEVICE_FOUND_UDEV)
- /* If udev says the device is around, it's around */
- device_set_state(d, DEVICE_PLUGGED);
- else if (d->found != DEVICE_NOT_FOUND && d->deserialized_state != DEVICE_PLUGGED)
- /* If a device is found in /proc/self/mountinfo or
- * /proc/swaps, and was not yet announced via udev,
- * it's "tentatively" around. */
- device_set_state(d, DEVICE_TENTATIVE);
+ /* First, let's put the deserialized state and found mask into effect, if we have it. */
+
+ if (d->deserialized_state < 0 ||
+ (d->deserialized_state == d->state &&
+ d->deserialized_found == d->found))
+ return 0;
+
+ d->found = d->deserialized_found;
+ device_set_state(d, d->deserialized_state);
+ return 0;
+}
+
+static void device_catchup(Unit *u) {
+ Device *d = DEVICE(u);
+
+ assert(d);
+
+ /* Second, let's update the state with the enumerated state if it's different */
+ if (d->enumerated_found == d->found)
+ return;
+
+ device_update_found_one(d, d->enumerated_found, DEVICE_FOUND_MASK);
+}
+
+static const struct {
+ DeviceFound flag;
+ const char *name;
+} device_found_map[] = {
+ { DEVICE_FOUND_UDEV, "found-udev" },
+ { DEVICE_FOUND_MOUNT, "found-mount" },
+ { DEVICE_FOUND_SWAP, "found-swap" },
+};
+
+static int device_found_to_string_many(DeviceFound flags, char **ret) {
+ _cleanup_free_ char *s = NULL;
+ unsigned i;
+
+ assert(ret);
+
+ for (i = 0; i < ELEMENTSOF(device_found_map); i++) {
+ if (!FLAGS_SET(flags, device_found_map[i].flag))
+ continue;
+
+ if (!strextend_with_separator(&s, ",", device_found_map[i].name, NULL))
+ return -ENOMEM;
+ }
+
+ *ret = TAKE_PTR(s);
return 0;
}
+static int device_found_from_string_many(const char *name, DeviceFound *ret) {
+ DeviceFound flags = 0;
+ int r;
+
+ assert(ret);
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ DeviceFound f = 0;
+ unsigned i;
+
+ r = extract_first_word(&name, &word, ",", 0);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ for (i = 0; i < ELEMENTSOF(device_found_map); i++)
+ if (streq(word, device_found_map[i].name)) {
+ f = device_found_map[i].flag;
+ break;
+ }
+
+ if (f == 0)
+ return -EINVAL;
+
+ flags |= f;
+ }
+
+ *ret = flags;
+ return 0;
+}
+
static int device_serialize(Unit *u, FILE *f, FDSet *fds) {
+ _cleanup_free_ char *s = NULL;
Device *d = DEVICE(u);
assert(u);
@@ -166,11 +228,15 @@ static int device_serialize(Unit *u, FILE *f, FDSet *fds) {
unit_serialize_item(u, f, "state", device_state_to_string(d->state));
+ if (device_found_to_string_many(d->found, &s) >= 0)
+ unit_serialize_item(u, f, "found", s);
+
return 0;
}
static int device_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
Device *d = DEVICE(u);
+ int r;
assert(u);
assert(key);
@@ -182,9 +248,15 @@ static int device_deserialize_item(Unit *u, const char *key, const char *value,
state = device_state_from_string(value);
if (state < 0)
- log_unit_debug(u, "Failed to parse state value: %s", value);
+ log_unit_debug(u, "Failed to parse state value, ignoring: %s", value);
else
d->deserialized_state = state;
+
+ } else if (streq(key, "found")) {
+ r = device_found_from_string_many(value, &d->deserialized_found);
+ if (r < 0)
+ log_unit_debug_errno(u, r, "Failed to parse found value, ignoring: %s", value);
+
} else
log_unit_debug(u, "Unknown serialization key: %s", key);
@@ -193,14 +265,27 @@ static int device_deserialize_item(Unit *u, const char *key, const char *value,
static void device_dump(Unit *u, FILE *f, const char *prefix) {
Device *d = DEVICE(u);
+ _cleanup_free_ char *s = NULL;
assert(d);
+ (void) device_found_to_string_many(d->found, &s);
+
fprintf(f,
"%sDevice State: %s\n"
- "%sSysfs Path: %s\n",
+ "%sSysfs Path: %s\n"
+ "%sFound: %s\n",
prefix, device_state_to_string(d->state),
- prefix, strna(d->sysfs));
+ prefix, strna(d->sysfs),
+ prefix, strna(s));
+
+ if (!strv_isempty(d->wants_property)) {
+ char **i;
+
+ STRV_FOREACH(i, d->wants_property)
+ fprintf(f, "%sudev SYSTEMD_WANTS: %s\n",
+ prefix, *i);
+ }
}
_pure_ static UnitActiveState device_active_state(Unit *u) {
@@ -241,26 +326,27 @@ static int device_update_description(Unit *u, struct udev_device *dev, const cha
_cleanup_free_ char *j;
j = strjoin(model, " ", label);
- if (j)
- r = unit_set_description(u, j);
- else
- r = -ENOMEM;
+ if (!j)
+ return log_oom();
+
+ r = unit_set_description(u, j);
} else
r = unit_set_description(u, model);
} else
r = unit_set_description(u, path);
-
if (r < 0)
- log_unit_error_errno(u, r, "Failed to set device description: %m");
+ return log_unit_error_errno(u, r, "Failed to set device description: %m");
- return r;
+ return 0;
}
static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
+ _cleanup_strv_free_ char **added = NULL;
const char *wants, *property;
+ Device *d = DEVICE(u);
int r;
- assert(u);
+ assert(d);
assert(dev);
property = MANAGER_IS_USER(u->manager) ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
@@ -274,21 +360,21 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
r = extract_first_word(&wants, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
- return 0;
+ break;
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_unit_error_errno(u, r, "Failed to parse property %s with value %s: %m", property, wants);
- if (unit_name_is_valid(word, UNIT_NAME_TEMPLATE) && DEVICE(u)->sysfs) {
+ if (unit_name_is_valid(word, UNIT_NAME_TEMPLATE) && d->sysfs) {
_cleanup_free_ char *escaped = NULL;
/* If the unit name is specified as template, then automatically fill in the sysfs path of the
* device as instance name, properly escaped. */
- r = unit_name_path_escape(DEVICE(u)->sysfs, &escaped);
+ r = unit_name_path_escape(d->sysfs, &escaped);
if (r < 0)
- return log_unit_error_errno(u, r, "Failed to escape %s: %m", DEVICE(u)->sysfs);
+ return log_unit_error_errno(u, r, "Failed to escape %s: %m", d->sysfs);
r = unit_name_replace_instance(word, escaped, &k);
if (r < 0)
@@ -296,7 +382,7 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
} else {
/* If this is not a template, then let's mangle it so, that it becomes a valid unit name. */
- r = unit_name_mangle(word, UNIT_NAME_NOGLOB, &k);
+ r = unit_name_mangle(word, UNIT_NAME_MANGLE_WARN, &k);
if (r < 0)
return log_unit_error_errno(u, r, "Failed to mangle unit name \"%s\": %m", word);
}
@@ -304,7 +390,43 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
r = unit_add_dependency_by_name(u, UNIT_WANTS, k, NULL, true, UNIT_DEPENDENCY_UDEV);
if (r < 0)
return log_unit_error_errno(u, r, "Failed to add Wants= dependency: %m");
+
+ r = strv_push(&added, k);
+ if (r < 0)
+ return log_oom();
+
+ k = NULL;
}
+
+ if (d->state != DEVICE_DEAD) {
+ char **i;
+
+ /* So here's a special hack, to compensate for the fact that the udev database's reload cycles are not
+ * synchronized with our own reload cycles: when we detect that the SYSTEMD_WANTS property of a device
+ * changes while the device unit is already up, let's manually trigger any new units listed in it not
+ * seen before. This typically appens during the boot-time switch root transition, as udev devices
+ * will generally already be up in the initrd, but SYSTEMD_WANTS properties get then added through udev
+ * rules only available on the host system, and thus only when the initial udev coldplug trigger runs.
+ *
+ * We do this only if the device has been up already when we parse this, as otherwise the usual
+ * dependency logic that is run from the dead → plugged transition will trigger these deps. */
+
+ STRV_FOREACH(i, added) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+
+ if (strv_contains(d->wants_property, *i)) /* Was this unit already listed before? */
+ continue;
+
+ r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, &error, NULL);
+ if (r < 0)
+ log_unit_warning_errno(u, r, "Failed to enqueue SYSTEMD_WANTS= job, ignoring: %s", bus_error_message(&error, r));
+ }
+ }
+
+ strv_free(d->wants_property);
+ d->wants_property = TAKE_PTR(added);
+
+ return 0;
}
static bool device_is_bound_by_mounts(Device *d, struct udev_device *dev) {
@@ -327,7 +449,7 @@ static bool device_is_bound_by_mounts(Device *d, struct udev_device *dev) {
return d->bind_mounts;
}
-static int device_upgrade_mount_deps(Unit *u) {
+static void device_upgrade_mount_deps(Unit *u) {
Unit *other;
Iterator i;
void *v;
@@ -341,9 +463,8 @@ static int device_upgrade_mount_deps(Unit *u) {
r = unit_add_dependency(other, UNIT_BINDS_TO, u, true, UNIT_DEPENDENCY_UDEV);
if (r < 0)
- return r;
+ log_unit_warning_errno(u, r, "Failed to add BindsTo= dependency between device and mount unit, ignoring: %m");
}
- return 0;
}
static int device_setup_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
@@ -358,8 +479,10 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
if (dev) {
sysfs = udev_device_get_syspath(dev);
- if (!sysfs)
+ if (!sysfs) {
+ log_debug("Couldn't get syspath from udev device, ignoring.");
return 0;
+ }
}
r = unit_name_from_path(path, ".device", &e);
@@ -368,17 +491,21 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
u = manager_get_unit(m, e);
if (u) {
- /* The device unit can still be present even if the device was unplugged: a mount unit can reference it hence
- * preventing the GC to have garbaged it. That's desired since the device unit may have a dependency on the
- * mount unit which was added during the loading of the later. */
- if (dev && DEVICE(u)->state == DEVICE_PLUGGED) {
-
- /* This unit is in plugged state: we're sure it's attached to a device. */
- if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
- log_unit_debug(u, "Dev %s appeared twice with different sysfs paths %s and %s",
- e, DEVICE(u)->sysfs, sysfs);
- return -EEXIST;
- }
+ /* The device unit can still be present even if the device was unplugged: a mount unit can reference it
+ * hence preventing the GC to have garbaged it. That's desired since the device unit may have a
+ * dependency on the mount unit which was added during the loading of the later. When the device is
+ * plugged the sysfs might not be initialized yet, as we serialize the device's state but do not
+ * serialize the sysfs path across reloads/reexecs. Hence, when coming back from a reload/restart we
+ * might have the state valid, but not the sysfs path. Hence, let's filter out conflicting devices, but
+ * let's accept devices in any state with no sysfs path set. */
+
+ if (DEVICE(u)->state == DEVICE_PLUGGED &&
+ DEVICE(u)->sysfs &&
+ sysfs &&
+ !path_equal(DEVICE(u)->sysfs, sysfs)) {
+ log_unit_debug(u, "Device %s appeared twice with different sysfs paths %s and %s, ignoring the latter.",
+ e, DEVICE(u)->sysfs, sysfs);
+ return -EEXIST;
}
delete = false;
@@ -390,24 +517,26 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
delete = true;
r = unit_new_for_name(m, sizeof(Device), e, &u);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to allocate device unit %s: %m", e);
goto fail;
+ }
unit_add_to_load_queue(u);
}
- /* If this was created via some dependency and has not
- * actually been seen yet ->sysfs will not be
+ /* If this was created via some dependency and has not actually been seen yet ->sysfs will not be
* initialized. Hence initialize it if necessary. */
if (sysfs) {
r = device_set_sysfs(DEVICE(u), sysfs);
- if (r < 0)
+ if (r < 0) {
+ log_error_errno(r, "Failed to set sysfs path %s for device unit %s: %m", sysfs, e);
goto fail;
+ }
(void) device_update_description(u, dev, path);
- /* The additional systemd udev properties we only interpret
- * for the main object */
+ /* The additional systemd udev properties we only interpret for the main object */
if (main)
(void) device_add_udev_wants(u, dev);
}
@@ -419,13 +548,11 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
device_upgrade_mount_deps(u);
/* Note that this won't dispatch the load queue, the caller has to do that if needed and appropriate */
-
unit_add_to_dbus_queue(u);
+
return 0;
fail:
- log_unit_warning_errno(u, r, "Failed to set up device unit: %m");
-
if (delete)
unit_free(u);
@@ -462,8 +589,7 @@ static int device_process_new(Manager *m, struct udev_device *dev) {
/* Don't bother with the /dev/block links */
p = udev_list_entry_get_name(item);
- if (path_startswith(p, "/dev/block/") ||
- path_startswith(p, "/dev/char/"))
+ if (PATH_STARTSWITH_SET(p, "/dev/block/", "/dev/char/"))
continue;
/* Verify that the symlink in the FS actually belongs
@@ -489,76 +615,81 @@ static int device_process_new(Manager *m, struct udev_device *dev) {
r = extract_first_word(&alias, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
- return 0;
+ break;
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_warning_errno(r, "Failed to add parse SYSTEMD_ALIAS for %s: %m", sysfs);
- if (path_is_absolute(word))
- (void) device_setup_unit(m, dev, word, false);
- else
+ if (!path_is_absolute(word))
log_warning("SYSTEMD_ALIAS for %s is not an absolute path, ignoring: %s", sysfs, word);
+ else if (!path_is_normalized(word))
+ log_warning("SYSTEMD_ALIAS for %s is not a normalized path, ignoring: %s", sysfs, word);
+ else
+ (void) device_setup_unit(m, dev, word, false);
}
-}
-static void device_update_found_one(Device *d, bool add, DeviceFound found, bool now) {
- DeviceFound n, previous;
+ return 0;
+}
+static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) {
assert(d);
- n = add ? (d->found | found) : (d->found & ~found);
- if (n == d->found)
- return;
-
- previous = d->found;
- d->found = n;
-
- if (!now)
- return;
-
/* Didn't exist before, but does now? if so, generate a new invocation ID for it */
- if (previous == DEVICE_NOT_FOUND && d->found != DEVICE_NOT_FOUND)
+ if (previous == DEVICE_NOT_FOUND && now != DEVICE_NOT_FOUND)
(void) unit_acquire_invocation_id(UNIT(d));
- if (d->found & DEVICE_FOUND_UDEV)
- /* When the device is known to udev we consider it
- * plugged. */
+ if (FLAGS_SET(now, DEVICE_FOUND_UDEV))
+ /* When the device is known to udev we consider it plugged. */
device_set_state(d, DEVICE_PLUGGED);
- else if (d->found != DEVICE_NOT_FOUND && (previous & DEVICE_FOUND_UDEV) == 0)
- /* If the device has not been seen by udev yet, but is
- * now referenced by the kernel, then we assume the
+ else if (now != DEVICE_NOT_FOUND && !FLAGS_SET(previous, DEVICE_FOUND_UDEV))
+ /* If the device has not been seen by udev yet, but is now referenced by the kernel, then we assume the
* kernel knows it now, and udev might soon too. */
device_set_state(d, DEVICE_TENTATIVE);
- else {
- /* If nobody sees the device, or if the device was
- * previously seen by udev and now is only referenced
- * from the kernel, then we consider the device is
- * gone, the kernel just hasn't noticed it yet. */
-
+ else
+ /* If nobody sees the device, or if the device was previously seen by udev and now is only referenced
+ * from the kernel, then we consider the device is gone, the kernel just hasn't noticed it yet. */
device_set_state(d, DEVICE_DEAD);
- device_unset_sysfs(d);
- }
+}
+
+static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) {
+ assert(d);
+
+ if (MANAGER_IS_RUNNING(UNIT(d)->manager)) {
+ DeviceFound n, previous;
+
+ /* When we are already running, then apply the new mask right-away, and trigger state changes
+ * right-away */
+
+ n = (d->found & ~mask) | (found & mask);
+ if (n == d->found)
+ return;
+
+ previous = d->found;
+ d->found = n;
+ device_found_changed(d, previous, n);
+ } else
+ /* We aren't running yet, let's apply the new mask to the shadow variable instead, which we'll apply as
+ * soon as we catch-up with the state. */
+ d->enumerated_found = (d->enumerated_found & ~mask) | (found & mask);
}
-static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) {
+static void device_update_found_by_sysfs(Manager *m, const char *sysfs, DeviceFound found, DeviceFound mask) {
Device *d, *l, *n;
assert(m);
assert(sysfs);
- if (found == DEVICE_NOT_FOUND)
- return 0;
+ if (mask == 0)
+ return;
l = hashmap_get(m->devices_by_sysfs, sysfs);
LIST_FOREACH_SAFE(same_sysfs, d, n, l)
- device_update_found_one(d, add, found, now);
-
- return 0;
+ device_update_found_one(d, found, mask);
}
-static int device_update_found_by_name(Manager *m, const char *path, bool add, DeviceFound found, bool now) {
+static int device_update_found_by_name(Manager *m, const char *path, DeviceFound found, DeviceFound mask) {
_cleanup_free_ char *e = NULL;
Unit *u;
int r;
@@ -566,7 +697,7 @@ static int device_update_found_by_name(Manager *m, const char *path, bool add, D
assert(m);
assert(path);
- if (found == DEVICE_NOT_FOUND)
+ if (mask == 0)
return 0;
r = unit_name_from_path(path, ".device", &e);
@@ -577,7 +708,7 @@ static int device_update_found_by_name(Manager *m, const char *path, bool add, D
if (!u)
return 0;
- device_update_found_one(DEVICE(u), add, found, now);
+ device_update_found_one(DEVICE(u), found, mask);
return 0;
}
@@ -619,7 +750,7 @@ static Unit *device_following(Unit *u) {
static int device_following_set(Unit *u, Set **_set) {
Device *d = DEVICE(u), *other;
- Set *set;
+ _cleanup_set_free_ Set *set = NULL;
int r;
assert(d);
@@ -637,38 +768,29 @@ static int device_following_set(Unit *u, Set **_set) {
LIST_FOREACH_AFTER(same_sysfs, other, d) {
r = set_put(set, other);
if (r < 0)
- goto fail;
+ return r;
}
LIST_FOREACH_BEFORE(same_sysfs, other, d) {
r = set_put(set, other);
if (r < 0)
- goto fail;
+ return r;
}
- *_set = set;
+ *_set = TAKE_PTR(set);
return 1;
-
-fail:
- set_free(set);
- return r;
}
static void device_shutdown(Manager *m) {
assert(m);
m->udev_event_source = sd_event_source_unref(m->udev_event_source);
-
- if (m->udev_monitor) {
- udev_monitor_unref(m->udev_monitor);
- m->udev_monitor = NULL;
- }
-
+ m->udev_monitor = udev_monitor_unref(m->udev_monitor);
m->devices_by_sysfs = hashmap_free(m->devices_by_sysfs);
}
static void device_enumerate(Manager *m) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
@@ -677,7 +799,7 @@ static void device_enumerate(Manager *m) {
if (!m->udev_monitor) {
m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
if (!m->udev_monitor) {
- log_oom();
+ log_error_errno(errno, "Failed to allocate udev monitor: %m");
goto fail;
}
@@ -709,7 +831,7 @@ static void device_enumerate(Manager *m) {
e = udev_enumerate_new(m->udev);
if (!e) {
- log_oom();
+ log_error_errno(errno, "Failed to alloacte udev enumerator: %m");
goto fail;
}
@@ -733,14 +855,20 @@ static void device_enumerate(Manager *m) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
const char *sysfs;
sysfs = udev_list_entry_get_name(item);
dev = udev_device_new_from_syspath(m->udev, sysfs);
if (!dev) {
- log_oom();
+ if (errno == ENOMEM) {
+ log_oom();
+ goto fail;
+ }
+
+ /* If we can't create a device, don't bother, it probably just disappeared. */
+ log_debug_errno(errno, "Failed to create udev device object for %s: %m", sysfs);
continue;
}
@@ -748,8 +876,7 @@ static void device_enumerate(Manager *m) {
continue;
(void) device_process_new(m, dev);
-
- device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, false);
+ device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
}
return;
@@ -758,8 +885,26 @@ fail:
device_shutdown(m);
}
+static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) {
+ Device *d, *l, *n;
+ int r;
+
+ assert(m);
+ assert(sysfs);
+
+ l = hashmap_get(m->devices_by_sysfs, sysfs);
+ LIST_FOREACH_SAFE(same_sysfs, d, n, l) {
+ if (d->state == DEVICE_DEAD)
+ continue;
+
+ r = manager_propagate_reload(m, UNIT(d), JOB_REPLACE, NULL);
+ if (r < 0)
+ log_warning_errno(r, "Failed to propagate reload, ignoring: %m");
+ }
+}
+
static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
Manager *m = userdata;
const char *action, *sysfs;
int r;
@@ -769,7 +914,7 @@ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
if (revents != EPOLLIN) {
static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
- if (ratelimit_test(&limit))
+ if (ratelimit_below(&limit))
log_warning("Failed to get udev event");
if (!(revents & EPOLLIN))
return 0;
@@ -795,20 +940,8 @@ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
return 0;
}
- if (streq(action, "change")) {
- Unit *u;
- Device *d, *l, *n;
-
- l = hashmap_get(m->devices_by_sysfs, sysfs);
- LIST_FOREACH_SAFE(same_sysfs, d, n, l) {
- u = &d->meta;
- if (u && UNIT_VTABLE(u)->active_state(u) == UNIT_ACTIVE) {
- r = manager_propagate_reload(m, u, JOB_REPLACE, NULL);
- if (r < 0)
- log_error_errno(r, "Failed to propagate reload: %m");
- }
- }
- }
+ if (streq(action, "change"))
+ device_propagate_reload_by_sysfs(m, sysfs);
/* A change event can signal that a device is becoming ready, in particular if
* the device is using the SYSTEMD_READY logic in udev
@@ -816,12 +949,12 @@ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
if (streq(action, "remove")) {
r = swap_process_device_remove(m, dev);
if (r < 0)
- log_error_errno(r, "Failed to process swap device remove event: %m");
+ log_warning_errno(r, "Failed to process swap device remove event, ignoring: %m");
/* If we get notified that a device was removed by
* udev, then it's completely gone, hence unset all
* found bits */
- device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP, true);
+ device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
} else if (device_is_ready(dev)) {
@@ -829,19 +962,19 @@ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
r = swap_process_device_new(m, dev);
if (r < 0)
- log_error_errno(r, "Failed to process swap device new event: %m");
+ log_warning_errno(r, "Failed to process swap device new event, ignoring: %m");
manager_dispatch_load_queue(m);
/* The device is found now, set the udev found bit */
- device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, true);
+ device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
} else {
/* The device is nominally around, but not ready for
* us. Hence unset the udev bit, but leave the rest
* around. */
- device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV, true);
+ device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV);
}
return 0;
@@ -859,61 +992,88 @@ static bool device_supported(void) {
return read_only <= 0;
}
-int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now) {
- _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
+static int validate_node(Manager *m, const char *node, struct udev_device **ret) {
struct stat st;
+ int r;
assert(m);
assert(node);
+ assert(ret);
- if (!device_supported())
- return 0;
+ /* Validates a device node that showed up in /proc/swaps or /proc/self/mountinfo if it makes sense for us to
+ * track. Note that this validator is fine within missing device nodes, but not with badly set up ones! */
- /* This is called whenever we find a device referenced in
- * /proc/swaps or /proc/self/mounts. Such a device might be
- * mounted/enabled at a time where udev has not finished
- * probing it yet, and we thus haven't learned about it
- * yet. In this case we will set the device unit to
- * "tentative" state. */
+ if (!path_startswith(node, "/dev")) {
+ *ret = NULL;
+ return 0; /* bad! */
+ }
- if (add) {
- if (!path_startswith(node, "/dev"))
- return 0;
+ if (stat(node, &st) < 0) {
+ if (errno != ENOENT)
+ return log_error_errno(errno, "Failed to stat() device node file %s: %m", node);
- /* We make an extra check here, if the device node
- * actually exists. If it's missing, then this is an
- * indication that device was unplugged but is still
- * referenced in /proc/swaps or
- * /proc/self/mountinfo. Note that this check doesn't
- * really cover all cases where a device might be gone
- * away, since drives that can have a medium inserted
- * will still have a device node even when the medium
- * is not there... */
+ *ret = NULL;
+ return 1; /* good! (though missing) */
- if (stat(node, &st) >= 0) {
- if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
- return 0;
+ } else {
+ _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
+
+ r = udev_device_new_from_stat_rdev(m->udev, &st, &dev);
+ if (r == -ENOENT) {
+ *ret = NULL;
+ return 1; /* good! (though missing) */
+ } else if (r == -ENOTTY) {
+ *ret = NULL;
+ return 0; /* bad! (not a device node but some other kind of file system node) */
+ } else if (r < 0)
+ return log_error_errno(r, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
+
+ *ret = TAKE_PTR(dev);
+ return 1; /* good! */
+ }
+}
- dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
- if (!dev && errno != ENOENT)
- return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
+void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
+ int r;
- } else if (errno != ENOENT)
- return log_error_errno(errno, "Failed to stat device node file %s: %m", node);
+ assert(m);
+ assert(node);
+
+ if (!device_supported())
+ return;
+
+ if (mask == 0)
+ return;
+
+ /* This is called whenever we find a device referenced in /proc/swaps or /proc/self/mounts. Such a device might
+ * be mounted/enabled at a time where udev has not finished probing it yet, and we thus haven't learned about
+ * it yet. In this case we will set the device unit to "tentative" state.
+ *
+ * This takes a pair of DeviceFound flags parameters. The 'mask' parameter is a bit mask that indicates which
+ * bits of 'found' to copy into the per-device DeviceFound flags field. Thus, this function may be used to set
+ * and unset individual bits in a single call, while merging partially with previous state. */
+
+ if ((found & mask) != 0) {
+ _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
- /* If the device is known in the kernel and newly
- * appeared, then we'll create a device unit for it,
- * under the name referenced in /proc/swaps or
- * /proc/self/mountinfo. */
+ /* If the device is known in the kernel and newly appeared, then we'll create a device unit for it,
+ * under the name referenced in /proc/swaps or /proc/self/mountinfo. But first, let's validate if
+ * everything is alright with the device node. */
+
+ r = validate_node(m, node, &dev);
+ if (r <= 0)
+ return; /* Don't create a device unit for this if the device node is borked. */
(void) device_setup_unit(m, dev, node, false);
}
/* Update the device unit's state, should it exist */
- return device_update_found_by_name(m, node, add, found, now);
+ (void) device_update_found_by_name(m, node, found, mask);
}
bool device_shall_be_bound_by(Unit *device, Unit *u) {
+ assert(device);
+ assert(u);
if (u->type != UNIT_MOUNT)
return false;
@@ -935,6 +1095,7 @@ const UnitVTable device_vtable = {
.load = unit_load_fragment_and_dropin_optional,
.coldplug = device_coldplug,
+ .catchup = device_catchup,
.serialize = device_serialize,
.deserialize_item = device_deserialize_item,
diff --git a/src/core/device.h b/src/core/device.h
index a551e7748a..a119b33e57 100644
--- a/src/core/device.h
+++ b/src/core/device.h
@@ -1,51 +1,43 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "unit.h"
typedef struct Device Device;
+/* A mask specifying where we have seen the device currently. This is a bitmask because the device might show up
+ * asynchronously from each other at various places. For example, in very common case a device might already be mounted
+ * before udev finished probing it (think: a script setting up a loopback block device, formatting it and mounting it
+ * in quick succession). Hence we need to track precisely where it is already visible and where not. */
typedef enum DeviceFound {
- DEVICE_NOT_FOUND = 0,
- DEVICE_FOUND_UDEV = 1,
- DEVICE_FOUND_MOUNT = 2,
- DEVICE_FOUND_SWAP = 4,
+ DEVICE_NOT_FOUND = 0,
+ DEVICE_FOUND_UDEV = 1U << 1, /* The device has shown up in the udev database */
+ DEVICE_FOUND_MOUNT = 1U << 2, /* The device has shown up in /proc/self/mountinfo */
+ DEVICE_FOUND_SWAP = 1U << 3, /* The device has shown up in /proc/swaps */
+ DEVICE_FOUND_MASK = DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP,
} DeviceFound;
struct Device {
Unit meta;
char *sysfs;
- DeviceFound found;
- /* In order to be able to distinguish dependencies on
- different device nodes we might end up creating multiple
- devices for the same sysfs path. We chain them up here. */
+ /* In order to be able to distinguish dependencies on different device nodes we might end up creating multiple
+ * devices for the same sysfs path. We chain them up here. */
LIST_FIELDS(struct Device, same_sysfs);
DeviceState state, deserialized_state;
+ DeviceFound found, deserialized_found, enumerated_found;
bool bind_mounts;
+
+ /* The SYSTEMD_WANTS udev property for this device the last time we saw it */
+ char **wants_property;
};
extern const UnitVTable device_vtable;
-int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now);
+void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask);
bool device_shall_be_bound_by(Unit *device, Unit *u);
+
+DEFINE_CAST(DEVICE, Device);
diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c
index 3da31bf870..7c5111ddf6 100644
--- a/src/core/dynamic-user.c
+++ b/src/core/dynamic-user.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <grp.h>
#include <pwd.h>
@@ -30,6 +12,7 @@
#include "io-util.h"
#include "parse-util.h"
#include "random-util.h"
+#include "socket-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "user-util.h"
@@ -319,10 +302,7 @@ static int pick_uid(char **suggested_paths, const char *name, uid_t *ret_uid) {
(void) make_uid_symlinks(candidate, name, true); /* also add direct lookup symlinks */
*ret_uid = candidate;
- r = lock_fd;
- lock_fd = -1;
-
- return r;
+ return TAKE_FD(lock_fd);
next:
;
@@ -354,7 +334,7 @@ static int dynamic_user_pop(DynamicUser *d, uid_t *ret_uid, int *ret_lock_fd) {
/* Read the UID and lock fd that is stored in the storage AF_UNIX socket. This should be called with the lock
* on the socket taken. */
- k = recvmsg(d->storage_socket[0], &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
+ k = recvmsg(d->storage_socket[0], &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (k < 0)
return -errno;
@@ -563,7 +543,7 @@ static int dynamic_user_realize(
return 0;
}
-static int dynamic_user_current(DynamicUser *d, uid_t *ret) {
+int dynamic_user_current(DynamicUser *d, uid_t *ret) {
_cleanup_(unlockfp) int storage_socket0_lock = -1;
_cleanup_close_ int lock_fd = -1;
uid_t uid;
@@ -770,8 +750,7 @@ int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret) {
if (check_uid != uid) /* lock file doesn't match our own idea */
return -ESRCH;
- *ret = user;
- user = NULL;
+ *ret = TAKE_PTR(user);
return 0;
}
diff --git a/src/core/dynamic-user.h b/src/core/dynamic-user.h
index b073c65837..791a8ba0ef 100644
--- a/src/core/dynamic-user.h
+++ b/src/core/dynamic-user.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct DynamicUser DynamicUser;
typedef struct DynamicCreds {
@@ -48,6 +29,7 @@ int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds);
void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds);
void dynamic_user_vacuum(Manager *m, bool close_user);
+int dynamic_user_current(DynamicUser *d, uid_t *ret);
int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret);
int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret);
diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c
index 3d37a986bc..76e1124cff 100644
--- a/src/core/emergency-action.c
+++ b/src/core/emergency-action.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
- Copyright 2012 Michael Olbrich
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Michael Olbrich
***/
#include <sys/reboot.h>
diff --git a/src/core/emergency-action.h b/src/core/emergency-action.h
index 4079e8499a..61791f176f 100644
--- a/src/core/emergency-action.h
+++ b/src/core/emergency-action.h
@@ -2,23 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
- Copyright 2012 Michael Olbrich
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Michael Olbrich
***/
typedef enum EmergencyAction {
diff --git a/src/core/execute.c b/src/core/execute.c
index 2f4b70ab3b..8ac69d1a0f 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -99,6 +81,7 @@
#include "selinux-util.h"
#include "signal-util.h"
#include "smack-util.h"
+#include "socket-util.h"
#include "special.h"
#include "stat-util.h"
#include "string-table.h"
@@ -119,7 +102,7 @@
#define SNDBUF_SIZE (8*1024*1024)
-static int shift_fds(int fds[], unsigned n_fds) {
+static int shift_fds(int fds[], size_t n_fds) {
int start, restart_from;
if (n_fds <= 0)
@@ -164,8 +147,8 @@ static int shift_fds(int fds[], unsigned n_fds) {
return 0;
}
-static int flags_fds(const int fds[], unsigned n_storage_fds, unsigned n_socket_fds, bool nonblock) {
- unsigned i, n_fds;
+static int flags_fds(const int fds[], size_t n_storage_fds, size_t n_socket_fds, bool nonblock) {
+ size_t i, n_fds;
int r;
n_fds = n_storage_fds + n_socket_fds;
@@ -1126,7 +1109,7 @@ static int setup_pam(
gid_t gid,
const char *tty,
char ***env,
- int fds[], unsigned n_fds) {
+ int fds[], size_t n_fds) {
#if HAVE_PAM
@@ -1300,10 +1283,7 @@ static int setup_pam(
if (!barrier_place_and_sync(&barrier))
log_error("PAM initialization failed");
- strv_free(*env);
- *env = e;
-
- return 0;
+ return strv_free_and_replace(*env, e);
fail:
if (pam_code != PAM_SUCCESS) {
@@ -1609,7 +1589,7 @@ static int build_environment(
const Unit *u,
const ExecContext *c,
const ExecParameters *p,
- unsigned n_fds,
+ size_t n_fds,
const char *home,
const char *username,
const char *shell,
@@ -1618,7 +1598,7 @@ static int build_environment(
char ***ret) {
_cleanup_strv_free_ char **our_env = NULL;
- unsigned n_env = 0;
+ size_t n_env = 0;
char *x;
assert(u);
@@ -1636,7 +1616,7 @@ static int build_environment(
return -ENOMEM;
our_env[n_env++] = x;
- if (asprintf(&x, "LISTEN_FDS=%u", n_fds) < 0)
+ if (asprintf(&x, "LISTEN_FDS=%zu", n_fds) < 0)
return -ENOMEM;
our_env[n_env++] = x;
@@ -1733,8 +1713,7 @@ static int build_environment(
our_env[n_env++] = NULL;
assert(n_env <= 12);
- *ret = our_env;
- our_env = NULL;
+ *ret = TAKE_PTR(our_env);
return 0;
}
@@ -1758,13 +1737,11 @@ static int build_pass_environment(const ExecContext *c, char ***ret) {
if (!GREEDY_REALLOC(pass_env, n_bufsize, n_env + 2))
return -ENOMEM;
- pass_env[n_env++] = x;
+ pass_env[n_env++] = TAKE_PTR(x);
pass_env[n_env] = NULL;
- x = NULL;
}
- *ret = pass_env;
- pass_env = NULL;
+ *ret = TAKE_PTR(pass_env);
return 0;
}
@@ -1798,6 +1775,7 @@ static bool exec_needs_mount_namespace(
return true;
if (context->private_devices ||
+ context->private_mounts ||
context->protect_system != PROTECT_SYSTEM_NO ||
context->protect_home != PROTECT_HOME_NO ||
context->protect_kernel_tunables ||
@@ -1805,8 +1783,20 @@ static bool exec_needs_mount_namespace(
context->protect_control_groups)
return true;
- if (context->mount_apivfs && (context->root_image || context->root_directory))
- return true;
+ if (context->root_directory) {
+ ExecDirectoryType t;
+
+ if (context->mount_apivfs)
+ return true;
+
+ for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
+ if (!params->prefix[t])
+ continue;
+
+ if (!strv_isempty(context->directories[t].paths))
+ return true;
+ }
+ }
if (context->dynamic_user &&
(!strv_isempty(context->directories[EXEC_DIRECTORY_STATE].paths) ||
@@ -2051,7 +2041,7 @@ static int setup_exec_directory(
}
/* First set up private root if it doesn't exist yet, with access mode 0700 and owned by root:root */
- r = mkdir_safe_label(private_root, 0700, 0, 0, false);
+ r = mkdir_safe_label(private_root, 0700, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -2107,10 +2097,10 @@ static int setup_exec_directory(
}
} else {
r = mkdir_label(p, context->directories[type].mode);
- if (r == -EEXIST)
- continue;
- if (r < 0)
+ if (r < 0 && r != -EEXIST)
goto fail;
+ if (r == -EEXIST && !context->dynamic_user)
+ continue;
}
/* Don't change the owner of the configuration directory, as in the common case it is not written to by
@@ -2168,12 +2158,12 @@ static int compile_bind_mounts(
const ExecContext *context,
const ExecParameters *params,
BindMount **ret_bind_mounts,
- unsigned *ret_n_bind_mounts,
+ size_t *ret_n_bind_mounts,
char ***ret_empty_directories) {
_cleanup_strv_free_ char **empty_directories = NULL;
BindMount *bind_mounts;
- unsigned n, h = 0, i;
+ size_t n, h = 0, i;
ExecDirectoryType t;
int r;
@@ -2238,7 +2228,8 @@ static int compile_bind_mounts(
continue;
if (context->dynamic_user &&
- !IN_SET(t, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION)) {
+ !IN_SET(t, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION) &&
+ !(context->root_directory || context->root_image)) {
char *private_root;
/* So this is for a dynamic user, and we need to make sure the process can access its own
@@ -2269,7 +2260,15 @@ static int compile_bind_mounts(
goto finish;
}
- d = strdup(s);
+ if (context->dynamic_user &&
+ !IN_SET(t, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION) &&
+ (context->root_directory || context->root_image))
+ /* When RootDirectory= or RootImage= are set, then the symbolic link to the private
+ * directory is not created on the root directory. So, let's bind-mount the directory
+ * on the 'non-private' place. */
+ d = strjoin(params->prefix[t], "/", *suffix);
+ else
+ d = strdup(s);
if (!d) {
free(s);
r = -ENOMEM;
@@ -2290,9 +2289,7 @@ static int compile_bind_mounts(
*ret_bind_mounts = bind_mounts;
*ret_n_bind_mounts = n;
- *ret_empty_directories = empty_directories;
-
- empty_directories = NULL;
+ *ret_empty_directories = TAKE_PTR(empty_directories);
return (int) n;
@@ -2311,10 +2308,10 @@ static int apply_mount_namespace(
_cleanup_strv_free_ char **empty_directories = NULL;
char *tmp = NULL, *var = NULL;
const char *root_dir = NULL, *root_image = NULL;
- NamespaceInfo ns_info = {};
+ NamespaceInfo ns_info;
bool needs_sandboxing;
BindMount *bind_mounts = NULL;
- unsigned n_bind_mounts = 0;
+ size_t n_bind_mounts = 0;
int r;
assert(context);
@@ -2341,16 +2338,7 @@ static int apply_mount_namespace(
if (r < 0)
return r;
- /*
- * If DynamicUser=no and RootDirectory= is set then lets pass a relaxed
- * sandbox info, otherwise enforce it, don't ignore protected paths and
- * fail if we are enable to apply the sandbox inside the mount namespace.
- */
- if (!context->dynamic_user && root_dir)
- ns_info.ignore_protect_paths = true;
-
needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & EXEC_COMMAND_FULLY_PRIVILEGED);
-
if (needs_sandboxing)
ns_info = (NamespaceInfo) {
.ignore_protect_paths = false,
@@ -2359,7 +2347,19 @@ static int apply_mount_namespace(
.protect_kernel_tunables = context->protect_kernel_tunables,
.protect_kernel_modules = context->protect_kernel_modules,
.mount_apivfs = context->mount_apivfs,
+ .private_mounts = context->private_mounts,
+ };
+ else if (!context->dynamic_user && root_dir)
+ /*
+ * If DynamicUser=no and RootDirectory= is set then lets pass a relaxed
+ * sandbox info, otherwise enforce it, don't ignore protected paths and
+ * fail if we are enable to apply the sandbox inside the mount namespace.
+ */
+ ns_info = (NamespaceInfo) {
+ .ignore_protect_paths = true,
};
+ else
+ ns_info = (NamespaceInfo) {};
r = setup_namespace(root_dir, root_image,
&ns_info, context->read_write_paths,
@@ -2441,7 +2441,9 @@ static int setup_keyring(
uid_t uid, gid_t gid) {
key_serial_t keyring;
- int r;
+ int r = 0;
+ uid_t saved_uid;
+ gid_t saved_gid;
assert(u);
assert(context);
@@ -2460,6 +2462,26 @@ static int setup_keyring(
if (context->keyring_mode == EXEC_KEYRING_INHERIT)
return 0;
+ /* Acquiring a reference to the user keyring is nasty. We briefly change identity in order to get things set up
+ * properly by the kernel. If we don't do that then we can't create it atomically, and that sucks for parallel
+ * execution. This mimics what pam_keyinit does, too. Setting up session keyring, to be owned by the right user
+ * & group is just as nasty as acquiring a reference to the user keyring. */
+
+ saved_uid = getuid();
+ saved_gid = getgid();
+
+ if (gid_is_valid(gid) && gid != saved_gid) {
+ if (setregid(gid, -1) < 0)
+ return log_unit_error_errno(u, errno, "Failed to change GID for user keyring: %m");
+ }
+
+ if (uid_is_valid(uid) && uid != saved_uid) {
+ if (setreuid(uid, -1) < 0) {
+ r = log_unit_error_errno(u, errno, "Failed to change UID for user keyring: %m");
+ goto out;
+ }
+ }
+
keyring = keyctl(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
if (keyring == -1) {
if (errno == ENOSYS)
@@ -2469,12 +2491,36 @@ static int setup_keyring(
else if (errno == EDQUOT)
log_unit_debug_errno(u, errno, "Out of kernel keyrings to allocate, ignoring.");
else
- return log_unit_error_errno(u, errno, "Setting up kernel keyring failed: %m");
+ r = log_unit_error_errno(u, errno, "Setting up kernel keyring failed: %m");
- return 0;
+ goto out;
+ }
+
+ /* When requested link the user keyring into the session keyring. */
+ if (context->keyring_mode == EXEC_KEYRING_SHARED) {
+
+ if (keyctl(KEYCTL_LINK,
+ KEY_SPEC_USER_KEYRING,
+ KEY_SPEC_SESSION_KEYRING, 0, 0) < 0) {
+ r = log_unit_error_errno(u, errno, "Failed to link user keyring into session keyring: %m");
+ goto out;
+ }
+ }
+
+ /* Restore uid/gid back */
+ if (uid_is_valid(uid) && uid != saved_uid) {
+ if (setreuid(saved_uid, -1) < 0) {
+ r = log_unit_error_errno(u, errno, "Failed to change UID back for user keyring: %m");
+ goto out;
+ }
}
- /* Populate they keyring with the invocation ID by default. */
+ if (gid_is_valid(gid) && gid != saved_gid) {
+ if (setregid(saved_gid, -1) < 0)
+ return log_unit_error_errno(u, errno, "Failed to change GID back for user keyring: %m");
+ }
+
+ /* Populate they keyring with the invocation ID by default, as original saved_uid. */
if (!sd_id128_is_null(u->invocation_id)) {
key_serial_t key;
@@ -2485,68 +2531,23 @@ static int setup_keyring(
if (keyctl(KEYCTL_SETPERM, key,
KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH|
KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH, 0, 0) < 0)
- return log_unit_error_errno(u, errno, "Failed to restrict invocation ID permission: %m");
+ r = log_unit_error_errno(u, errno, "Failed to restrict invocation ID permission: %m");
}
}
- /* And now, make the keyring owned by the service's user */
- if (uid_is_valid(uid) || gid_is_valid(gid))
- if (keyctl(KEYCTL_CHOWN, keyring, uid, gid, 0) < 0)
- return log_unit_error_errno(u, errno, "Failed to change ownership of session keyring: %m");
+out:
+ /* Revert back uid & gid for the the last time, and exit */
+ /* no extra logging, as only the first already reported error matters */
+ if (getuid() != saved_uid)
+ (void) setreuid(saved_uid, -1);
- /* When requested link the user keyring into the session keyring. */
- if (context->keyring_mode == EXEC_KEYRING_SHARED) {
- uid_t saved_uid;
- gid_t saved_gid;
+ if (getgid() != saved_gid)
+ (void) setregid(saved_gid, -1);
- /* Acquiring a reference to the user keyring is nasty. We briefly change identity in order to get things
- * set up properly by the kernel. If we don't do that then we can't create it atomically, and that
- * sucks for parallel execution. This mimics what pam_keyinit does, too.*/
-
- saved_uid = getuid();
- saved_gid = getgid();
-
- if (gid_is_valid(gid) && gid != saved_gid) {
- if (setregid(gid, -1) < 0)
- return log_unit_error_errno(u, errno, "Failed to change GID for user keyring: %m");
- }
-
- if (uid_is_valid(uid) && uid != saved_uid) {
- if (setreuid(uid, -1) < 0) {
- (void) setregid(saved_gid, -1);
- return log_unit_error_errno(u, errno, "Failed to change UID for user keyring: %m");
- }
- }
-
- if (keyctl(KEYCTL_LINK,
- KEY_SPEC_USER_KEYRING,
- KEY_SPEC_SESSION_KEYRING, 0, 0) < 0) {
-
- r = -errno;
-
- (void) setreuid(saved_uid, -1);
- (void) setregid(saved_gid, -1);
-
- return log_unit_error_errno(u, r, "Failed to link user keyring into session keyring: %m");
- }
-
- if (uid_is_valid(uid) && uid != saved_uid) {
- if (setreuid(saved_uid, -1) < 0) {
- (void) setregid(saved_gid, -1);
- return log_unit_error_errno(u, errno, "Failed to change UID back for user keyring: %m");
- }
- }
-
- if (gid_is_valid(gid) && gid != saved_gid) {
- if (setregid(saved_gid, -1) < 0)
- return log_unit_error_errno(u, errno, "Failed to change GID back for user keyring: %m");
- }
- }
-
- return 0;
+ return r;
}
-static void append_socket_pair(int *array, unsigned *n, const int pair[2]) {
+static void append_socket_pair(int *array, size_t *n, const int pair[2]) {
assert(array);
assert(n);
@@ -2565,9 +2566,9 @@ static int close_remaining_fds(
const DynamicCreds *dcreds,
int user_lookup_fd,
int socket_fd,
- int *fds, unsigned n_fds) {
+ int *fds, size_t n_fds) {
- unsigned n_dont_close = 0;
+ size_t n_dont_close = 0;
int dont_close[n_fds + 12];
assert(params);
@@ -2699,8 +2700,7 @@ static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p
}
}
- *ret = list;
- list = NULL;
+ *ret = TAKE_PTR(list);
return 0;
}
@@ -2718,8 +2718,8 @@ static int exec_child(
int socket_fd,
int named_iofds[3],
int *fds,
- unsigned n_storage_fds,
- unsigned n_socket_fds,
+ size_t n_storage_fds,
+ size_t n_socket_fds,
char **files_env,
int user_lookup_fd,
int *exit_status) {
@@ -2747,8 +2747,8 @@ static int exec_child(
#endif
uid_t uid = UID_INVALID;
gid_t gid = GID_INVALID;
- int i, r, ngids = 0;
- unsigned n_fds;
+ int r, ngids = 0;
+ size_t n_fds;
ExecDirectoryType dt;
int secure_bits;
@@ -2936,15 +2936,9 @@ static int exec_child(
}
if (context->oom_score_adjust_set) {
- char t[DECIMAL_STR_MAX(context->oom_score_adjust)];
-
- /* When we can't make this change due to EPERM, then
- * let's silently skip over it. User namespaces
- * prohibit write access to this file, and we
- * shouldn't trip up over that. */
-
- sprintf(t, "%i", context->oom_score_adjust);
- r = write_string_file("/proc/self/oom_score_adj", t, 0);
+ /* When we can't make this change due to EPERM, then let's silently skip over it. User namespaces
+ * prohibit write access to this file, and we shouldn't trip up over that. */
+ r = set_oom_score_adjust(context->oom_score_adjust);
if (IN_SET(r, -EPERM, -EACCES))
log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
else if (r < 0) {
@@ -3187,17 +3181,12 @@ static int exec_child(
if (needs_sandboxing) {
uint64_t bset;
+ int which_failed;
- for (i = 0; i < _RLIMIT_MAX; i++) {
-
- if (!context->rlimit[i])
- continue;
-
- r = setrlimit_closest(i, context->rlimit[i]);
- if (r < 0) {
- *exit_status = EXIT_LIMITS;
- return log_unit_error_errno(unit, r, "Failed to adjust resource limit %s: %m", rlimit_to_string(i));
- }
+ r = setrlimit_closest_all((const struct rlimit* const *) context->rlimit, &which_failed);
+ if (r < 0) {
+ *exit_status = EXIT_LIMITS;
+ return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed));
}
/* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly requested. */
@@ -3397,8 +3386,7 @@ static int exec_child(
return log_oom();
}
- strv_free(accum_env);
- accum_env = ee;
+ strv_free_and_replace(accum_env, ee);
}
final_argv = replace_env_argv(argv, accum_env);
@@ -3411,29 +3399,24 @@ static int exec_child(
_cleanup_free_ char *line;
line = exec_command_line(final_argv);
- if (line) {
+ if (line)
log_struct(LOG_DEBUG,
"EXECUTABLE=%s", command->path,
LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
LOG_UNIT_ID(unit),
- LOG_UNIT_INVOCATION_ID(unit),
- NULL);
- }
+ LOG_UNIT_INVOCATION_ID(unit));
}
execve(command->path, final_argv, accum_env);
if (errno == ENOENT && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
-
log_struct_errno(LOG_INFO, errno,
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
LOG_UNIT_ID(unit),
LOG_UNIT_INVOCATION_ID(unit),
LOG_UNIT_MESSAGE(unit, "Executable %s missing, skipping: %m",
command->path),
- "EXECUTABLE=%s", command->path,
- NULL);
-
+ "EXECUTABLE=%s", command->path);
return 0;
}
@@ -3454,7 +3437,7 @@ int exec_spawn(Unit *unit,
_cleanup_strv_free_ char **files_env = NULL;
int *fds = NULL;
- unsigned n_storage_fds = 0, n_socket_fds = 0;
+ size_t n_storage_fds = 0, n_socket_fds = 0;
_cleanup_free_ char *line = NULL;
int socket_fd, r;
int named_iofds[3] = { -1, -1, -1 };
@@ -3507,8 +3490,7 @@ int exec_spawn(Unit *unit,
LOG_UNIT_MESSAGE(unit, "About to execute: %s", line),
"EXECUTABLE=%s", command->path,
LOG_UNIT_ID(unit),
- LOG_UNIT_INVOCATION_ID(unit),
- NULL);
+ LOG_UNIT_INVOCATION_ID(unit));
pid = fork();
if (pid < 0)
@@ -3533,7 +3515,7 @@ int exec_spawn(Unit *unit,
unit->manager->user_lookup_fds[1],
&exit_status);
- if (r < 0) {
+ if (r < 0)
log_struct_errno(LOG_ERR, r,
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
LOG_UNIT_ID(unit),
@@ -3541,9 +3523,7 @@ int exec_spawn(Unit *unit,
LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD),
command->path),
- "EXECUTABLE=%s", command->path,
- NULL);
- }
+ "EXECUTABLE=%s", command->path);
_exit(exit_status);
}
@@ -3580,7 +3560,8 @@ void exec_context_init(ExecContext *c) {
for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
c->directories[i].mode = 0755;
c->capability_bounding_set = CAP_ALL;
- c->restrict_namespaces = NAMESPACE_FLAGS_ALL;
+ assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL);
+ c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL;
c->log_level_max = -1;
}
@@ -3595,8 +3576,7 @@ void exec_context_done(ExecContext *c) {
c->pass_environment = strv_free(c->pass_environment);
c->unset_environment = strv_free(c->unset_environment);
- for (l = 0; l < ELEMENTSOF(c->rlimit); l++)
- c->rlimit[l] = mfree(c->rlimit[l]);
+ rlimit_free_all(c->rlimit);
for (l = 0; l < 3; l++) {
c->stdio_fdname[l] = mfree(c->stdio_fdname[l]);
@@ -3679,8 +3659,8 @@ static void exec_command_done(ExecCommand *c) {
c->argv = strv_free(c->argv);
}
-void exec_command_done_array(ExecCommand *c, unsigned n) {
- unsigned i;
+void exec_command_done_array(ExecCommand *c, size_t n) {
+ size_t i;
for (i = 0; i < n; i++)
exec_command_done(c+i);
@@ -3698,8 +3678,8 @@ ExecCommand* exec_command_free_list(ExecCommand *c) {
return NULL;
}
-void exec_command_free_array(ExecCommand **c, unsigned n) {
- unsigned i;
+void exec_command_free_array(ExecCommand **c, size_t n) {
+ size_t i;
for (i = 0; i < n; i++)
c[i] = exec_command_free_list(c[i]);
@@ -3745,9 +3725,9 @@ const char* exec_context_fdname(const ExecContext *c, int fd_index) {
}
static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[3]) {
- unsigned i, targets;
+ size_t i, targets;
const char* stdio_fdname[3];
- unsigned n_fds;
+ size_t n_fds;
assert(c);
assert(p);
@@ -3996,9 +3976,9 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
for (i = 0; i < RLIM_NLIMITS; i++)
if (c->rlimit[i]) {
- fprintf(f, "%s%s: " RLIM_FMT "\n",
+ fprintf(f, "Limit%s%s: " RLIM_FMT "\n",
prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
- fprintf(f, "%s%sSoft: " RLIM_FMT "\n",
+ fprintf(f, "Limit%s%sSoft: " RLIM_FMT "\n",
prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur);
}
@@ -4283,7 +4263,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
if (exec_context_restrict_namespaces_set(c)) {
_cleanup_free_ char *s = NULL;
- r = namespace_flag_to_string_many(c->restrict_namespaces, &s);
+ r = namespace_flags_to_string(c->restrict_namespaces, &s);
if (r >= 0)
fprintf(f, "%sRestrictNamespaces: %s\n",
prefix, s);
@@ -4510,10 +4490,7 @@ int exec_command_set(ExecCommand *c, const char *path, ...) {
free(c->path);
c->path = p;
- strv_free(c->argv);
- c->argv = l;
-
- return 0;
+ return strv_free_and_replace(c->argv, l);
}
int exec_command_append(ExecCommand *c, const char *path, ...) {
@@ -4860,12 +4837,11 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value,
} else
return 0;
-
/* If the object is newly created, then put it to the hashmap which manages ExecRuntime objects. */
if (rt_create) {
r = hashmap_put(u->manager->exec_runtime_by_id, rt_create->id, rt_create);
if (r < 0) {
- log_unit_debug_errno(u, r, "Failed to put runtime paramter to manager's storage: %m");
+ log_unit_debug_errno(u, r, "Failed to put runtime parameter to manager's storage: %m");
return 0;
}
diff --git a/src/core/execute.h b/src/core/execute.h
index a34cf0b873..77ffe82323 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct ExecStatus ExecStatus;
typedef struct ExecCommand ExecCommand;
typedef struct ExecContext ExecContext;
@@ -218,9 +199,9 @@ struct ExecContext {
char **read_write_paths, **read_only_paths, **inaccessible_paths;
unsigned long mount_flags;
BindMount *bind_mounts;
- unsigned n_bind_mounts;
+ size_t n_bind_mounts;
TemporaryFileSystem *temporary_filesystems;
- unsigned n_temporary_filesystems;
+ size_t n_temporary_filesystems;
uint64_t capability_bounding_set;
uint64_t capability_ambient_set;
@@ -241,6 +222,7 @@ struct ExecContext {
bool private_network;
bool private_devices;
bool private_users;
+ bool private_mounts;
ProtectSystem protect_system;
ProtectHome protect_home;
bool protect_kernel_tunables;
@@ -292,20 +274,20 @@ static inline bool exec_context_restrict_namespaces_set(const ExecContext *c) {
}
typedef enum ExecFlags {
- EXEC_APPLY_SANDBOXING = 1U << 0,
- EXEC_APPLY_CHROOT = 1U << 1,
- EXEC_APPLY_TTY_STDIN = 1U << 2,
- EXEC_NEW_KEYRING = 1U << 3,
- EXEC_PASS_LOG_UNIT = 1U << 4, /* Whether to pass the unit name to the service's journal stream connection */
- EXEC_CHOWN_DIRECTORIES = 1U << 5, /* chown() the runtime/state/cache/log directories to the user we run as, under all conditions */
- EXEC_NSS_BYPASS_BUS = 1U << 6, /* Set the SYSTEMD_NSS_BYPASS_BUS environment variable, to disable nss-systemd for dbus */
- EXEC_CGROUP_DELEGATE = 1U << 7,
+ EXEC_APPLY_SANDBOXING = 1 << 0,
+ EXEC_APPLY_CHROOT = 1 << 1,
+ EXEC_APPLY_TTY_STDIN = 1 << 2,
+ EXEC_NEW_KEYRING = 1 << 3,
+ EXEC_PASS_LOG_UNIT = 1 << 4, /* Whether to pass the unit name to the service's journal stream connection */
+ EXEC_CHOWN_DIRECTORIES = 1 << 5, /* chown() the runtime/state/cache/log directories to the user we run as, under all conditions */
+ EXEC_NSS_BYPASS_BUS = 1 << 6, /* Set the SYSTEMD_NSS_BYPASS_BUS environment variable, to disable nss-systemd for dbus */
+ EXEC_CGROUP_DELEGATE = 1 << 7,
/* The following are not used by execute.c, but by consumers internally */
- EXEC_PASS_FDS = 1U << 8,
- EXEC_IS_CONTROL = 1U << 9,
- EXEC_SETENV_RESULT = 1U << 10,
- EXEC_SET_WATCHDOG = 1U << 11,
+ EXEC_PASS_FDS = 1 << 8,
+ EXEC_IS_CONTROL = 1 << 9,
+ EXEC_SETENV_RESULT = 1 << 10,
+ EXEC_SET_WATCHDOG = 1 << 11,
} ExecFlags;
struct ExecParameters {
@@ -314,8 +296,8 @@ struct ExecParameters {
int *fds;
char **fd_names;
- unsigned n_storage_fds;
- unsigned n_socket_fds;
+ size_t n_storage_fds;
+ size_t n_socket_fds;
ExecFlags flags;
bool selinux_context_net:1;
@@ -347,10 +329,10 @@ int exec_spawn(Unit *unit,
DynamicCreds *dynamic_creds,
pid_t *ret);
-void exec_command_done_array(ExecCommand *c, unsigned n);
+void exec_command_done_array(ExecCommand *c, size_t n);
ExecCommand* exec_command_free_list(ExecCommand *c);
-void exec_command_free_array(ExecCommand **c, unsigned n);
+void exec_command_free_array(ExecCommand **c, size_t n);
void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix);
void exec_command_append_list(ExecCommand **l, ExecCommand *e);
diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c
index 19299918cc..83cce88131 100644
--- a/src/core/hostname-setup.c
+++ b/src/core/hostname-setup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
diff --git a/src/core/hostname-setup.h b/src/core/hostname-setup.h
index 8bf8769859..dc7b9a6262 100644
--- a/src/core/hostname-setup.h
+++ b/src/core/hostname-setup.h
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int hostname_setup(void);
diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c
index 80319622ad..013d6c5de3 100644
--- a/src/core/ima-setup.c
+++ b/src/core/ima-setup.c
@@ -1,23 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright (C) 2012 Roberto Sassu - Politecnico di Torino, Italy
- TORSEC group — http://security.polito.it
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Roberto Sassu - Politecnico di Torino, Italy
+ TORSEC group — http://security.polito.it
***/
#include <errno.h>
diff --git a/src/core/ima-setup.h b/src/core/ima-setup.h
index 1eae74bceb..cf478795a1 100644
--- a/src/core/ima-setup.h
+++ b/src/core/ima-setup.h
@@ -2,24 +2,8 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright (C) 2012 Roberto Sassu - Politecnico di Torino, Italy
- TORSEC group — http://security.polito.it
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Roberto Sassu - Politecnico di Torino, Italy
+ TORSEC group — http://security.polito.it
***/
int ima_setup(void);
diff --git a/src/core/ip-address-access.c b/src/core/ip-address-access.c
index f10138c6de..1d431bb674 100644
--- a/src/core/ip-address-access.c
+++ b/src/core/ip-address-access.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
#include <stdlib.h>
diff --git a/src/core/ip-address-access.h b/src/core/ip-address-access.h
index 536142e904..7babf19562 100644
--- a/src/core/ip-address-access.h
+++ b/src/core/ip-address-access.h
@@ -1,25 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "conf-parser.h"
#include "in-addr-util.h"
#include "list.h"
@@ -32,7 +15,7 @@ struct IPAddressAccessItem {
LIST_FIELDS(IPAddressAccessItem, items);
};
-int config_parse_ip_address_access(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_address_access);
IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first);
diff --git a/src/core/job.c b/src/core/job.c
index 1b3534a7a6..734756b666 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
@@ -56,6 +38,7 @@ Job* job_new_raw(Unit *unit) {
j->manager = unit->manager;
j->unit = unit;
j->type = _JOB_TYPE_INVALID;
+ j->reloaded = false;
return j;
}
@@ -77,7 +60,7 @@ Job* job_new(Unit *unit, JobType type) {
return j;
}
-void job_free(Job *j) {
+void job_unlink(Job *j) {
assert(j);
assert(!j->installed);
assert(!j->transaction_prev);
@@ -85,16 +68,33 @@ void job_free(Job *j) {
assert(!j->subject_list);
assert(!j->object_list);
- if (j->in_run_queue)
+ if (j->in_run_queue) {
LIST_REMOVE(run_queue, j->manager->run_queue, j);
+ j->in_run_queue = false;
+ }
- if (j->in_dbus_queue)
+ if (j->in_dbus_queue) {
LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
+ j->in_dbus_queue = false;
+ }
- if (j->in_gc_queue)
+ if (j->in_gc_queue) {
LIST_REMOVE(gc_queue, j->manager->gc_job_queue, j);
+ j->in_gc_queue = false;
+ }
+
+ j->timer_event_source = sd_event_source_unref(j->timer_event_source);
+}
+
+void job_free(Job *j) {
+ assert(j);
+ assert(!j->installed);
+ assert(!j->transaction_prev);
+ assert(!j->transaction_next);
+ assert(!j->subject_list);
+ assert(!j->object_list);
- sd_event_source_unref(j->timer_event_source);
+ job_unlink(j);
sd_bus_track_unref(j->bus_track);
strv_free(j->deserialized_clients);
@@ -254,6 +254,7 @@ int job_install_deserialized(Job *j) {
*pj = j;
j->installed = true;
+ j->reloaded = true;
if (j->state == JOB_RUNNING)
j->unit->manager->n_running_jobs++;
@@ -576,7 +577,6 @@ int job_run_and_invalidate(Job *j) {
job_set_state(j, JOB_RUNNING);
job_add_to_dbus_queue(j);
-
switch (j->type) {
case JOB_VERIFY_ACTIVE: {
@@ -626,6 +626,8 @@ int job_run_and_invalidate(Job *j) {
r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true, false);
else if (r == -ENOLINK)
r = job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false);
+ else if (r == -ESTALE)
+ r = job_finish_and_invalidate(j, JOB_ONCE, true, false);
else if (r == -EAGAIN)
job_set_state(j, JOB_WAITING);
else if (r < 0)
@@ -645,6 +647,7 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
[JOB_ASSERT] = "Assertion failed for %s.",
[JOB_UNSUPPORTED] = "Starting of %s not supported.",
[JOB_COLLECTED] = "Unnecessary job for %s was removed.",
+ [JOB_ONCE] = "Unit %s has been started before and cannot be started again."
};
static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = {
[JOB_DONE] = "Stopped %s.",
@@ -704,6 +707,7 @@ static const struct {
[JOB_ASSERT] = { ANSI_HIGHLIGHT_YELLOW, "ASSERT" },
[JOB_UNSUPPORTED] = { ANSI_HIGHLIGHT_YELLOW, "UNSUPP" },
/* JOB_COLLECTED */
+ [JOB_ONCE] = { ANSI_HIGHLIGHT_RED, " ONCE " },
};
static void job_print_status_message(Unit *u, JobType t, JobResult result) {
@@ -761,6 +765,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
[JOB_ASSERT] = LOG_WARNING,
[JOB_UNSUPPORTED] = LOG_WARNING,
[JOB_COLLECTED] = LOG_INFO,
+ [JOB_ONCE] = LOG_ERR,
};
assert(u);
@@ -808,8 +813,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
"JOB_TYPE=%s", job_type_to_string(t),
"JOB_RESULT=%s", job_result_to_string(result),
LOG_UNIT_ID(u),
- LOG_UNIT_INVOCATION_ID(u),
- NULL);
+ LOG_UNIT_INVOCATION_ID(u));
return;
}
@@ -819,8 +823,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
"JOB_RESULT=%s", job_result_to_string(result),
LOG_UNIT_ID(u),
LOG_UNIT_INVOCATION_ID(u),
- mid,
- NULL);
+ mid);
}
static void job_emit_status_message(Unit *u, JobType t, JobResult result) {
@@ -853,6 +856,19 @@ static void job_fail_dependencies(Unit *u, UnitDependency d) {
}
}
+static int job_save_pending_finished_job(Job *j) {
+ int r;
+
+ assert(j);
+
+ r = set_ensure_allocated(&j->manager->pending_finished_jobs, NULL);
+ if (r < 0)
+ return r;
+
+ job_unlink(j);
+ return set_put(j->manager->pending_finished_jobs, j);
+}
+
int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already) {
Unit *u;
Unit *other;
@@ -892,7 +908,11 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
j->manager->n_failed_jobs++;
job_uninstall(j);
- job_free(j);
+ /* Keep jobs started before the reload to send singal later, free all others */
+ if (!MANAGER_IS_RELOADING(j->manager) ||
+ !j->reloaded ||
+ job_save_pending_finished_job(j) < 0)
+ job_free(j);
/* Fail depending jobs on failure */
if (result != JOB_DONE && recursive) {
@@ -916,8 +936,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
LOG_UNIT_MESSAGE(u, "Job %s/%s failed with result '%s'.",
u->id,
job_type_to_string(t),
- job_result_to_string(result)),
- NULL);
+ job_result_to_string(result)));
unit_start_on_failure(u);
}
@@ -1439,8 +1458,7 @@ int job_get_before(Job *j, Job*** ret) {
n = sort_job_list(list, n);
- *ret = list;
- list = NULL;
+ *ret = TAKE_PTR(list);
return (int) n;
}
@@ -1489,8 +1507,7 @@ int job_get_after(Job *j, Job*** ret) {
n = sort_job_list(list, n);
- *ret = list;
- list = NULL;
+ *ret = TAKE_PTR(list);
return (int) n;
}
@@ -1539,6 +1556,7 @@ static const char* const job_result_table[_JOB_RESULT_MAX] = {
[JOB_ASSERT] = "assert",
[JOB_UNSUPPORTED] = "unsupported",
[JOB_COLLECTED] = "collected",
+ [JOB_ONCE] = "once",
};
DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);
diff --git a/src/core/job.h b/src/core/job.h
index 2edb63169c..2f5f3f3989 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "sd-event.h"
@@ -109,6 +90,7 @@ enum JobResult {
JOB_ASSERT, /* Couldn't start a unit, because an assert didn't hold */
JOB_UNSUPPORTED, /* Couldn't start a unit, because the unit type is not supported on the system */
JOB_COLLECTED, /* Job was garbage collected, since nothing needed it anymore */
+ JOB_ONCE, /* Unit was started before, and hence can't be started again */
_JOB_RESULT_MAX,
_JOB_RESULT_INVALID = -1
};
@@ -174,10 +156,12 @@ struct Job {
bool irreversible:1;
bool in_gc_queue:1;
bool ref_by_private_bus:1;
+ bool reloaded:1;
};
Job* job_new(Unit *unit, JobType type);
Job* job_new_raw(Unit *unit);
+void job_unlink(Job *job);
void job_free(Job *job);
Job* job_install(Job *j);
int job_install_deserialized(Job *j);
diff --git a/src/core/kill.c b/src/core/kill.c
index 5dfcb780fa..929eebfe37 100644
--- a/src/core/kill.c
+++ b/src/core/kill.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "kill.h"
#include "signal-util.h"
diff --git a/src/core/kill.h b/src/core/kill.h
index f0d6ec41e9..2d6aa943a6 100644
--- a/src/core/kill.h
+++ b/src/core/kill.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct KillContext KillContext;
#include <stdbool.h>
diff --git a/src/core/killall.c b/src/core/killall.c
index daa9c4ea20..87d207fd3d 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 ProFUSION embedded systems
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 ProFUSION embedded systems
***/
#include <errno.h>
@@ -211,7 +196,6 @@ static int killall(int sig, Set *pids, bool send_sighup) {
make sure to only send this after SIGTERM so
that SIGTERM is always first in the queue. */
-
if (get_ctty_devnr(pid, NULL) >= 0)
/* it's OK if the process is gone, just ignore the result */
(void) kill(pid, SIGHUP);
diff --git a/src/core/killall.h b/src/core/killall.h
index 45e97ab594..cbd202651c 100644
--- a/src/core/killall.h
+++ b/src/core/killall.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "time-util.h"
void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout);
diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c
index a2809d03f6..9251929558 100644
--- a/src/core/kmod-setup.c
+++ b/src/core/kmod-setup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <ftw.h>
#include <string.h>
diff --git a/src/core/kmod-setup.h b/src/core/kmod-setup.h
index b5ea6b55a9..801c7bf699 100644
--- a/src/core/kmod-setup.h
+++ b/src/core/kmod-setup.h
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int kmod_setup(void);
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
index 57ed686d1f..4b422cc54e 100644
--- a/src/core/load-dropin.c
+++ b/src/core/load-dropin.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "conf-parser.h"
#include "fs-util.h"
@@ -31,26 +12,21 @@
#include "unit.h"
static int unit_name_compatible(const char *a, const char *b) {
- _cleanup_free_ char *prefix = NULL;
+ _cleanup_free_ char *template = NULL;
int r;
- /* the straightforward case: the symlink name matches the target */
+ /* The straightforward case: the symlink name matches the target */
if (streq(a, b))
return 1;
- r = unit_name_template(a, &prefix);
+ r = unit_name_template(a, &template);
if (r == -EINVAL)
- /* not a template */
- return 0;
+ return 0; /* Not a template */
if (r < 0)
- /* oom, or some other failure. Just skip the warning. */
- return r;
-
- /* an instance name points to a target that is just the template name */
- if (streq(prefix, b))
- return 1;
+ return r; /* OOM, or some other failure. Just skip the warning. */
- return 0;
+ /* An instance name points to a target that is just the template name */
+ return streq(template, b);
}
static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suffix) {
@@ -69,8 +45,8 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff
return r;
STRV_FOREACH(p, paths) {
- const char *entry;
_cleanup_free_ char *target = NULL;
+ const char *entry;
entry = basename(*p);
@@ -146,10 +122,9 @@ int unit_load_dropin(Unit *u) {
if (r <= 0)
return 0;
- if (!u->dropin_paths) {
- u->dropin_paths = l;
- l = NULL;
- } else {
+ if (!u->dropin_paths)
+ u->dropin_paths = TAKE_PTR(l);
+ else {
r = strv_extend_strv(&u->dropin_paths, l, true);
if (r < 0)
return log_oom();
diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h
index 4c8ab487b3..bb10a76338 100644
--- a/src/core/load-dropin.h
+++ b/src/core/load-dropin.h
@@ -1,31 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "dropin.h"
#include "unit.h"
/* Read service data supplementary drop-in directories */
static inline int unit_find_dropin_paths(Unit *u, char ***paths) {
+ assert(u);
+
return unit_file_find_dropin_conf_paths(NULL,
u->manager->lookup_paths.search_path,
u->manager->unit_path_cache,
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 5d90a7c054..15fb47838c 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -6,6 +6,8 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "conf-parser.h"
#include "load-fragment.h"
#include "missing.h"
+
+#include "all-units.h"
%}
struct ConfigPerfItem;
%null_strings
@@ -57,11 +59,11 @@ $1.SyslogLevelPrefix, config_parse_bool, 0,
$1.LogLevelMax, config_parse_log_level, 0, offsetof($1, exec_context.log_level_max)
$1.LogExtraFields, config_parse_log_extra_fields, 0, offsetof($1, exec_context)
$1.Capabilities, config_parse_warn_compat, DISABLED_LEGACY, offsetof($1, exec_context)
-$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context)
+$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context.secure_bits)
$1.CapabilityBoundingSet, config_parse_capability_set, 0, offsetof($1, exec_context.capability_bounding_set)
$1.AmbientCapabilities, config_parse_capability_set, 0, offsetof($1, exec_context.capability_ambient_set)
$1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec)
-$1.NoNewPrivileges, config_parse_no_new_privileges, 0, offsetof($1, exec_context)
+$1.NoNewPrivileges, config_parse_bool, 0, offsetof($1, exec_context.no_new_privileges)
$1.KeyringMode, config_parse_exec_keyring_mode, 0, offsetof($1, exec_context.keyring_mode)
m4_ifdef(`HAVE_SECCOMP',
`$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context)
@@ -80,22 +82,22 @@ $1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CO
$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
-$1.LimitCPU, config_parse_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
-$1.LimitFSIZE, config_parse_limit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
-$1.LimitDATA, config_parse_limit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
-$1.LimitSTACK, config_parse_limit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
-$1.LimitCORE, config_parse_limit, RLIMIT_CORE, offsetof($1, exec_context.rlimit)
-$1.LimitRSS, config_parse_limit, RLIMIT_RSS, offsetof($1, exec_context.rlimit)
-$1.LimitNOFILE, config_parse_limit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit)
-$1.LimitAS, config_parse_limit, RLIMIT_AS, offsetof($1, exec_context.rlimit)
-$1.LimitNPROC, config_parse_limit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit)
-$1.LimitMEMLOCK, config_parse_limit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit)
-$1.LimitLOCKS, config_parse_limit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit)
-$1.LimitSIGPENDING, config_parse_limit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit)
-$1.LimitMSGQUEUE, config_parse_limit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit)
-$1.LimitNICE, config_parse_limit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
-$1.LimitRTPRIO, config_parse_limit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
-$1.LimitRTTIME, config_parse_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
+$1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
+$1.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
+$1.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
+$1.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
+$1.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof($1, exec_context.rlimit)
+$1.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof($1, exec_context.rlimit)
+$1.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit)
+$1.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof($1, exec_context.rlimit)
+$1.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit)
+$1.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit)
+$1.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit)
+$1.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit)
+$1.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit)
+$1.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
+$1.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
+$1.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
$1.ReadWriteDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_paths)
$1.ReadOnlyDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_paths)
$1.InaccessibleDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths)
@@ -112,9 +114,10 @@ $1.ProtectKernelModules, config_parse_bool, 0,
$1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups)
$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network)
$1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users)
-$1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context)
-$1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context)
-$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context)
+$1.PrivateMounts, config_parse_bool, 0, offsetof($1, exec_context.private_mounts)
+$1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context.protect_system)
+$1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context.protect_home)
+$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context.mount_flags)
$1.MountAPIVFS, config_parse_bool, 0, offsetof($1, exec_context.mount_apivfs)
$1.Personality, config_parse_personality, 0, offsetof($1, exec_context.personality)
$1.RuntimeDirectoryPreserve, config_parse_runtime_preserve_mode, 0, offsetof($1, exec_context.runtime_directory_preserve_mode)
@@ -153,8 +156,8 @@ $1.KillSignal, config_parse_signal, 0,
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.CPUWeight, config_parse_cpu_weight, 0, offsetof($1, cgroup_context.cpu_weight)
-$1.StartupCPUWeight, config_parse_cpu_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight)
+$1.CPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.cpu_weight)
+$1.StartupCPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight)
$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares)
$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares)
$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context)
@@ -167,8 +170,8 @@ $1.MemoryLimit, config_parse_memory_limit, 0,
$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.IOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.io_accounting)
-$1.IOWeight, config_parse_io_weight, 0, offsetof($1, cgroup_context.io_weight)
-$1.StartupIOWeight, config_parse_io_weight, 0, offsetof($1, cgroup_context.startup_io_weight)
+$1.IOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.io_weight)
+$1.StartupIOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_io_weight)
$1.IODeviceWeight, config_parse_io_device_weight, 0, offsetof($1, cgroup_context)
$1.IOReadBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
$1.IOWriteBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
@@ -289,7 +292,7 @@ Service.ExecStopPost, config_parse_exec, SERVICE_EXE
Service.RestartSec, config_parse_sec, 0, offsetof(Service, restart_usec)
Service.TimeoutSec, config_parse_service_timeout, 0, 0
Service.TimeoutStartSec, config_parse_service_timeout, 0, 0
-Service.TimeoutStopSec, config_parse_service_timeout, 0, 0
+Service.TimeoutStopSec, config_parse_sec_fix_0, 0, offsetof(Service, timeout_stop_usec)
Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
m4_dnl The following five only exist for compatibility, they moved into Unit, see above
@@ -328,8 +331,8 @@ Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCK
Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0
Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0
Socket.ListenUSBFunction, config_parse_socket_listen, SOCKET_USB_FUNCTION, 0
-Socket.SocketProtocol, config_parse_socket_protocol, 0, 0
-Socket.BindIPv6Only, config_parse_socket_bind, 0, 0,
+Socket.SocketProtocol, config_parse_socket_protocol, 0, offsetof(Socket, socket_protocol)
+Socket.BindIPv6Only, config_parse_socket_bind, 0, offsetof(Socket, bind_ipv6_only)
Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog)
Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0
Socket.ExecStartPre, config_parse_exec, SOCKET_EXEC_START_PRE, offsetof(Socket, exec_command)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 5b30c47e83..d9a5094aa0 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2012 Holger Hans Peter Freyther
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Holger Hans Peter Freyther
***/
#include <errno.h>
@@ -33,6 +17,7 @@
#include "af-list.h"
#include "alloc-util.h"
+#include "all-units.h"
#include "bus-error.h"
#include "bus-internal.h"
#include "bus-util.h"
@@ -57,7 +42,6 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
-#include "rlimit-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
@@ -70,43 +54,45 @@
#include "strv.h"
#include "unit-name.h"
#include "unit-printf.h"
-#include "unit.h"
#include "user-util.h"
-#include "utf8.h"
#include "web-util.h"
-int config_parse_warn_compat(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- Disabled reason = ltype;
-
- switch(reason) {
- case DISABLED_CONFIGURATION:
- log_syntax(unit, LOG_DEBUG, filename, line, 0,
- "Support for option %s= has been disabled at compile time and it is ignored", lvalue);
- break;
- case DISABLED_LEGACY:
- log_syntax(unit, LOG_INFO, filename, line, 0,
- "Support for option %s= has been removed and it is ignored", lvalue);
- break;
- case DISABLED_EXPERIMENTAL:
- log_syntax(unit, LOG_INFO, filename, line, 0,
- "Support for option %s= has not yet been enabled and it is ignored", lvalue);
- break;
- };
+static int supported_socket_protocol_from_string(const char *s) {
+ int r;
- return 0;
+ if (isempty(s))
+ return IPPROTO_IP;
+
+ r = socket_protocol_from_name(s);
+ if (r < 0)
+ return -EINVAL;
+ if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP))
+ return -EPROTONOSUPPORT;
+
+ return r;
}
+DEFINE_CONFIG_PARSE(config_parse_socket_protocol, supported_socket_protocol_from_string, "Failed to parse socket protocol");
+DEFINE_CONFIG_PARSE(config_parse_exec_secure_bits, secure_bits_from_string, "Failed to parse secure bits");
DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_emergency_action, emergency_action, EmergencyAction, "Failed to parse failure action specifier");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "Failed to parse protect home value");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
+DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
+DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight");
+DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight");
+DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t, "Invalid CPU shares");
+DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag");
int config_parse_unit_deps(
const char *unit,
@@ -145,7 +131,7 @@ int config_parse_unit_deps(
r = unit_name_printf(u, word, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
continue;
}
@@ -198,7 +184,7 @@ int config_parse_unit_string_printf(
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: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
@@ -228,7 +214,7 @@ int config_parse_unit_strv_printf(
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: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
@@ -268,7 +254,7 @@ int config_parse_unit_path_printf(
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers in \"%s\"%s: %m",
+ "Failed to resolve unit specifiers in '%s'%s: %m",
rvalue, fatal ? "" : ", ignoring");
return fatal ? -ENOEXEC : 0;
}
@@ -320,22 +306,13 @@ int config_parse_unit_path_strv_printf(
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers on \"%s\", ignoring: %m", word);
- return 0;
- }
-
- if (!utf8_is_valid(k)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
return 0;
}
- if (!path_is_absolute(k)) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Symlink path is not absolute: %s", k);
+ r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
return 0;
- }
-
- path_kill_slashes(k);
r = strv_push(x, k);
if (r < 0)
@@ -378,47 +355,51 @@ int config_parse_socket_listen(const char *unit,
return log_oom();
if (ltype != SOCKET_SOCKET) {
+ _cleanup_free_ char *k = NULL;
- p->type = ltype;
- r = unit_full_printf(UNIT(s), rvalue, &p->path);
+ 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: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
- path_kill_slashes(p->path);
+ r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
+ return 0;
+
+ free_and_replace(p->path, k);
+ p->type = ltype;
} else if (streq(lvalue, "ListenNetlink")) {
_cleanup_free_ char *k = NULL;
- p->type = SOCKET_SOCKET;
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: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
r = socket_address_parse_netlink(&p->address, k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k);
return 0;
}
+ p->type = SOCKET_SOCKET;
+
} else {
_cleanup_free_ char *k = NULL;
- p->type = SOCKET_SOCKET;
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: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
r = socket_address_parse_and_warn(&p->address, k);
if (r < 0) {
if (r != -EAFNOSUPPORT)
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
-
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k);
return 0;
}
@@ -435,6 +416,8 @@ int config_parse_socket_listen(const char *unit,
log_syntax(unit, LOG_ERR, filename, line, 0, "Address family not supported, ignoring: %s", rvalue);
return 0;
}
+
+ p->type = SOCKET_SOCKET;
}
p->fd = -1;
@@ -450,72 +433,6 @@ int config_parse_socket_listen(const char *unit,
return 0;
}
-int config_parse_socket_protocol(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- Socket *s;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- s = SOCKET(data);
-
- r = socket_protocol_from_name(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid socket protocol, ignoring: %s", rvalue);
- return 0;
- } else if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue);
- return 0;
- }
-
- s->socket_protocol = r;
-
- return 0;
-}
-
-int config_parse_socket_bind(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Socket *s;
- SocketAddressBindIPv6Only b;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- s = SOCKET(data);
-
- b = parse_socket_address_bind_ipv6_only_or_bool(rvalue);
- if (b < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
- return 0;
- }
-
- s->bind_ipv6_only = b;
-
- return 0;
-}
-
int config_parse_exec_nice(
const char *unit,
const char *filename,
@@ -536,13 +453,17 @@ int config_parse_exec_nice(
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ c->nice_set = false;
+ return 0;
+ }
+
r = parse_nice(rvalue, &priority);
if (r < 0) {
if (r == -ERANGE)
log_syntax(unit, LOG_ERR, filename, line, r, "Nice priority out of range, ignoring: %s", rvalue);
else
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority, ignoring: %s", rvalue);
-
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority '%s', ignoring: %m", rvalue);
return 0;
}
@@ -552,16 +473,17 @@ int config_parse_exec_nice(
return 0;
}
-int config_parse_exec_oom_score_adjust(const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_exec_oom_score_adjust(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
ExecContext *c = data;
int oa, r;
@@ -571,14 +493,17 @@ int config_parse_exec_oom_score_adjust(const char* unit,
assert(rvalue);
assert(data);
- r = safe_atoi(rvalue, &oa);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
+ if (isempty(rvalue)) {
+ c->oom_score_adjust_set = false;
return 0;
}
- if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "OOM score adjust value out of range, ignoring: %s", rvalue);
+ r = parse_oom_score_adjust(rvalue, &oa);
+ if (r < 0) {
+ if (r == -ERANGE)
+ log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue);
+ else
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value '%s', ignoring: %m", rvalue);
return 0;
}
@@ -670,7 +595,7 @@ int config_parse_exec(
r = unit_full_printf(u, f, &path);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers on %s%s: %m",
+ "Failed to resolve unit specifiers in '%s'%s: %m",
f, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
@@ -678,29 +603,57 @@ int config_parse_exec(
if (isempty(path)) {
/* First word is either "-" or "@" with no command. */
log_syntax(unit, LOG_ERR, filename, line, 0,
- "Empty path in command line%s: \"%s\"",
+ "Empty path in command line%s: '%s'",
ignore ? ", ignoring" : "", rvalue);
return ignore ? 0 : -ENOEXEC;
}
if (!string_is_safe(path)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
- "Executable path contains special characters%s: %s",
- ignore ? ", ignoring" : "", rvalue);
- return ignore ? 0 : -ENOEXEC;
- }
- if (!path_is_absolute(path)) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Executable path is not absolute%s: %s",
- ignore ? ", ignoring" : "", rvalue);
+ "Executable name contains special characters%s: %s",
+ ignore ? ", ignoring" : "", path);
return ignore ? 0 : -ENOEXEC;
}
if (endswith(path, "/")) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Executable path specifies a directory%s: %s",
- ignore ? ", ignoring" : "", rvalue);
+ ignore ? ", ignoring" : "", path);
return ignore ? 0 : -ENOEXEC;
}
+ if (!path_is_absolute(path)) {
+ const char *prefix;
+ bool found = false;
+
+ if (!filename_is_valid(path)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Neither a valid executable name nor an absolute path%s: %s",
+ ignore ? ", ignoring" : "", path);
+ return ignore ? 0 : -ENOEXEC;
+ }
+
+ /* Resolve a single-component name to a full path */
+ NULSTR_FOREACH(prefix, DEFAULT_PATH_NULSTR) {
+ _cleanup_free_ char *fullpath = NULL;
+
+ fullpath = strjoin(prefix, "/", path);
+ if (!fullpath)
+ return log_oom();
+
+ if (access(fullpath, F_OK) >= 0) {
+ free_and_replace(path, fullpath);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Executable \"%s\" not found in path \"%s\"%s",
+ path, DEFAULT_PATH, ignore ? ", ignoring" : "");
+ return ignore ? 0 : -ENOEXEC;
+ }
+ }
+
if (!separate_argv0) {
char *w = NULL;
@@ -714,7 +667,7 @@ int config_parse_exec(
n[nlen] = NULL;
}
- path_kill_slashes(path);
+ path_simplify(path, false);
while (!isempty(p)) {
_cleanup_free_ char *word = NULL, *resolved = NULL;
@@ -756,16 +709,16 @@ int config_parse_exec(
r = unit_full_printf(u, word, &resolved);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers on %s%s: %m",
+ "Failed to resolve unit specifiers in %s%s: %m",
word, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- n[nlen++] = resolved;
+
+ n[nlen++] = TAKE_PTR(resolved);
n[nlen] = NULL;
- resolved = NULL;
}
if (!n || !n[0]) {
@@ -779,15 +732,13 @@ int config_parse_exec(
if (!nce)
return log_oom();
- nce->argv = n;
- nce->path = path;
+ nce->argv = TAKE_PTR(n);
+ nce->path = TAKE_PTR(path);
nce->flags = flags;
exec_command_append_list(e, nce);
/* Do not _cleanup_free_ these. */
- n = NULL;
- path = NULL;
nce = NULL;
rvalue = p;
@@ -796,9 +747,6 @@ int config_parse_exec(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
-
int config_parse_socket_bindtodevice(
const char* unit,
const char *filename,
@@ -812,27 +760,24 @@ int config_parse_socket_bindtodevice(
void *userdata) {
Socket *s = data;
- char *n;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (rvalue[0] && !streq(rvalue, "*")) {
- if (!ifname_valid(rvalue)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is invalid, ignoring: %s", rvalue);
- return 0;
- }
+ if (isempty(rvalue) || streq(rvalue, "*")) {
+ s->bind_to_device = mfree(s->bind_to_device);
+ return 0;
+ }
- n = strdup(rvalue);
- if (!n)
- return log_oom();
- } else
- n = NULL;
+ if (!ifname_valid(rvalue)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid interface name, ignoring: %s", rvalue);
+ return 0;
+ }
- free(s->bind_to_device);
- s->bind_to_device = n;
+ if (free_and_strdup(&s->bind_to_device, rvalue) < 0)
+ return log_oom();
return 0;
}
@@ -866,13 +811,13 @@ int config_parse_exec_input(
r = unit_full_printf(u, n, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s: %m", n);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n);
if (isempty(resolved))
resolved = mfree(resolved);
else if (!fdname_is_valid(resolved)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name: %s", resolved);
- return -EINVAL;
+ return -ENOEXEC;
}
free_and_replace(c->stdio_fdname[STDIN_FILENO], resolved);
@@ -884,17 +829,11 @@ int config_parse_exec_input(
r = unit_full_printf(u, n, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s: %m", n);
-
- if (!path_is_absolute(resolved)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "file: requires an absolute path name: %s", resolved);
- return -EINVAL;
- }
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n);
- if (!path_is_normalized(resolved)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "file: requires a normalized path name: %s", resolved);
- return -EINVAL;
- }
+ r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue);
+ if (r < 0)
+ return -ENOEXEC;
free_and_replace(c->stdio_file[STDIN_FILENO], resolved);
@@ -945,11 +884,11 @@ int config_parse_exec_input_text(
r = cunescape(rvalue, 0, &unescaped);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode C escaped text: %s", rvalue);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode C escaped text '%s': %m", rvalue);
r = unit_full_printf(u, unescaped, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers: %s", unescaped);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", unescaped);
sz = strlen(resolved);
if (c->stdin_data_size + sz + 1 < c->stdin_data_size || /* check for overflow */
@@ -1053,13 +992,13 @@ int config_parse_exec_output(
if (n) {
r = unit_full_printf(u, n, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s: %m", n);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
if (isempty(resolved))
resolved = mfree(resolved);
else if (!fdname_is_valid(resolved)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name: %s", resolved);
- return -EINVAL;
+ return -ENOEXEC;
}
eo = EXEC_OUTPUT_NAMED_FD;
@@ -1068,17 +1007,11 @@ int config_parse_exec_output(
r = unit_full_printf(u, n, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s: %m", n);
-
- if (!path_is_absolute(resolved)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "file: requires an absolute path name: %s", resolved);
- return -EINVAL;
- }
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
- if (!path_is_normalized(resolved)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "file: requires a normalized path name, ignoring: %s", resolved);
- return -EINVAL;
- }
+ r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue);
+ if (r < 0)
+ return -ENOEXEC;
eo = EXEC_OUTPUT_FILE;
@@ -1131,6 +1064,12 @@ int config_parse_exec_io_class(const char *unit,
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ c->ioprio_set = false;
+ c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
+ return 0;
+ }
+
x = ioprio_class_from_string(rvalue);
if (x < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue);
@@ -1162,6 +1101,12 @@ int config_parse_exec_io_priority(const char *unit,
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ c->ioprio_set = false;
+ c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
+ return 0;
+ }
+
r = ioprio_parse_priority(rvalue, &i);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue);
@@ -1185,7 +1130,6 @@ int config_parse_exec_cpu_sched_policy(const char *unit,
void *data,
void *userdata) {
-
ExecContext *c = data;
int x;
@@ -1194,6 +1138,13 @@ int config_parse_exec_cpu_sched_policy(const char *unit,
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ c->cpu_sched_set = false;
+ c->cpu_sched_policy = SCHED_OTHER;
+ c->cpu_sched_priority = 0;
+ return 0;
+ }
+
x = sched_policy_from_string(rvalue);
if (x < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
@@ -1229,7 +1180,7 @@ int config_parse_exec_cpu_sched_prio(const char *unit,
r = safe_atoi(rvalue, &i);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling priority, ignoring: %s", rvalue);
return 0;
}
@@ -1280,8 +1231,7 @@ int config_parse_exec_cpu_affinity(const char *unit,
}
if (!c->cpuset) {
- c->cpuset = cpuset;
- cpuset = NULL;
+ c->cpuset = TAKE_PTR(cpuset);
c->cpuset_ncpus = (unsigned) ncpus;
return 0;
}
@@ -1289,8 +1239,7 @@ int config_parse_exec_cpu_affinity(const char *unit,
if (c->cpuset_ncpus < (unsigned) ncpus) {
CPU_OR_S(CPU_ALLOC_SIZE(c->cpuset_ncpus), cpuset, c->cpuset, cpuset);
CPU_FREE(c->cpuset);
- c->cpuset = cpuset;
- cpuset = NULL;
+ c->cpuset = TAKE_PTR(cpuset);
c->cpuset_ncpus = (unsigned) ncpus;
return 0;
}
@@ -1300,45 +1249,6 @@ int config_parse_exec_cpu_affinity(const char *unit,
return 0;
}
-int config_parse_exec_secure_bits(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- /* An empty assignment resets the field */
- c->secure_bits = 0;
- return 0;
- }
-
- r = secure_bits_from_string(rvalue);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Invalid syntax, ignoring: %s", rvalue);
- return 0;
- }
-
- c->secure_bits = r;
-
- return 0;
-}
-
int config_parse_capability_set(
const char *unit,
const char *filename,
@@ -1371,10 +1281,8 @@ int config_parse_capability_set(
/* else "AmbientCapabilities" initialized to all bits off */
r = capability_set_from_string(rvalue, &sum);
- if (r == -ENOMEM)
- return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse word: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= specifier '%s', ignoring: %m", lvalue, rvalue);
return 0;
}
@@ -1392,109 +1300,6 @@ int config_parse_capability_set(
return 0;
}
-int config_parse_limit(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- struct rlimit **rl = data, d = {};
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = rlimit_parse(ltype, rvalue, &d);
- if (r == -EILSEQ) {
- log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue);
- return 0;
- }
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
-
- if (rl[ltype])
- *rl[ltype] = d;
- else {
- rl[ltype] = newdup(struct rlimit, &d, 1);
- if (!rl[ltype])
- return log_oom();
- }
-
- return 0;
-}
-
-#if HAVE_SYSV_COMPAT
-int config_parse_sysv_priority(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *priority = data;
- int i, r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = safe_atoi(rvalue, &i);
- if (r < 0 || i < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SysV start priority, ignoring: %s", rvalue);
- return 0;
- }
-
- *priority = (int) i;
- return 0;
-}
-#endif
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
-
-int config_parse_exec_mount_flags(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
-
- ExecContext *c = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = mount_propagation_flags_from_string(rvalue, &c->mount_flags);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue);
-
- return 0;
-}
-
int config_parse_exec_selinux_context(
const char *unit,
const char *filename,
@@ -1533,13 +1338,12 @@ int config_parse_exec_selinux_context(
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers%s: %m",
- ignore ? ", ignoring" : "");
+ "Failed to resolve unit specifiers in '%s'%s: %m",
+ rvalue, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
- free(c->selinux_context);
- c->selinux_context = k;
+ free_and_replace(c->selinux_context, k);
c->selinux_context_ignore = ignore;
return 0;
@@ -1583,13 +1387,12 @@ int config_parse_exec_apparmor_profile(
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers%s: %m",
- ignore ? ", ignoring" : "");
+ "Failed to resolve unit specifiers in '%s'%s: %m",
+ rvalue, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
- free(c->apparmor_profile);
- c->apparmor_profile = k;
+ free_and_replace(c->apparmor_profile, k);
c->apparmor_profile_ignore = ignore;
return 0;
@@ -1633,13 +1436,12 @@ int config_parse_exec_smack_process_label(
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers%s: %m",
- ignore ? ", ignoring" : "");
+ "Failed to resolve unit specifiers in '%s'%s: %m",
+ rvalue, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
- free(c->smack_process_label);
- c->smack_process_label = k;
+ free_and_replace(c->smack_process_label, k);
c->smack_process_label_ignore = ignore;
return 0;
@@ -1660,7 +1462,7 @@ int config_parse_timer(const char *unit,
usec_t usec = 0;
TimerValue *v;
TimerBase b;
- CalendarSpec *c = NULL;
+ _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
int r;
@@ -1684,7 +1486,7 @@ int config_parse_timer(const char *unit,
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
@@ -1693,22 +1495,19 @@ int config_parse_timer(const char *unit,
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse calendar specification, ignoring: %s", k);
return 0;
}
- } else {
+ } else
if (parse_sec(k, &usec) < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", k);
return 0;
}
- }
v = new0(TimerValue, 1);
- if (!v) {
- calendar_spec_free(c);
+ if (!v)
return log_oom();
- }
v->base = b;
v->value = usec;
- v->calendar_spec = c;
+ v->calendar_spec = TAKE_PTR(c);
LIST_PREPEND(value, t->values, v);
@@ -1744,7 +1543,7 @@ int config_parse_trigger_unit(
r = unit_name_printf(u, rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
@@ -1803,22 +1602,20 @@ int config_parse_path_spec(const char *unit,
r = unit_full_printf(UNIT(p), rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
- if (!path_is_absolute(k)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Path is not absolute, ignoring: %s", k);
+ r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
return 0;
- }
s = new0(PathSpec, 1);
if (!s)
return log_oom();
s->unit = UNIT(p);
- s->path = path_kill_slashes(k);
- k = NULL;
+ s->path = TAKE_PTR(k);
s->type = b;
s->inotify_fd = -1;
@@ -1852,7 +1649,7 @@ int config_parse_socket_service(
r = unit_name_printf(UNIT(s), rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
return -ENOEXEC;
}
@@ -1900,7 +1697,7 @@ int config_parse_fdname(
r = unit_full_printf(UNIT(s), rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
@@ -1949,7 +1746,7 @@ int config_parse_service_sockets(
r = unit_name_printf(UNIT(s), word, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
continue;
}
@@ -1993,12 +1790,12 @@ int config_parse_bus_name(
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: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
if (!service_name_is_valid(k)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name %s, ignoring.", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name, ignoring: %s", k);
return 0;
}
@@ -2026,26 +1823,21 @@ int config_parse_service_timeout(
assert(rvalue);
assert(s);
- /* This is called for three cases: TimeoutSec=, TimeoutStopSec= and TimeoutStartSec=. */
+ /* This is called for two cases: TimeoutSec= and TimeoutStartSec=. */
- r = parse_sec(rvalue, &usec);
+ /* Traditionally, these options accepted 0 to disable the timeouts. However, a timeout of 0 suggests it happens
+ * immediately, hence fix this to become USEC_INFINITY instead. This is in-line with how we internally handle
+ * all other timeouts. */
+ r = parse_sec_fix_0(rvalue, &usec);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue);
return 0;
}
- /* Traditionally, these options accepted 0 to disable the timeouts. However, a timeout of 0 suggests it happens
- * immediately, hence fix this to become USEC_INFINITY instead. This is in-line with how we internally handle
- * all other timeouts. */
- if (usec <= 0)
- usec = USEC_INFINITY;
-
- if (!streq(lvalue, "TimeoutStopSec")) {
- s->start_timeout_defined = true;
- s->timeout_start_usec = usec;
- }
+ s->start_timeout_defined = true;
+ s->timeout_start_usec = usec;
- if (!streq(lvalue, "TimeoutStartSec"))
+ if (streq(lvalue, "TimeoutSec"))
s->timeout_stop_usec = usec;
return 0;
@@ -2096,7 +1888,8 @@ int config_parse_user_group(
void *data,
void *userdata) {
- char **user = data, *n;
+ _cleanup_free_ char *k = NULL;
+ char **user = data;
Unit *u = userdata;
int r;
@@ -2105,30 +1898,23 @@ int config_parse_user_group(
assert(rvalue);
assert(u);
- if (isempty(rvalue))
- n = NULL;
- else {
- _cleanup_free_ char *k = NULL;
-
- r = unit_full_printf(u, rvalue, &k);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
- return -ENOEXEC;
- }
-
- if (!valid_user_group_name_or_id(k)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
- return -ENOEXEC;
- }
+ if (isempty(rvalue)) {
+ *user = mfree(*user);
+ return 0;
+ }
- n = k;
- k = NULL;
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
+ return -ENOEXEC;
}
- free(*user);
- *user = n;
+ if (!valid_user_group_name_or_id(k)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
+ return -ENOEXEC;
+ }
- return 0;
+ return free_and_replace(*user, k);
}
int config_parse_user_group_strv(
@@ -2145,7 +1931,7 @@ int config_parse_user_group_strv(
char ***users = data;
Unit *u = userdata;
- const char *p;
+ const char *p = rvalue;
int r;
assert(filename);
@@ -2158,7 +1944,6 @@ int config_parse_user_group_strv(
return 0;
}
- p = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
@@ -2216,6 +2001,12 @@ int config_parse_working_directory(
assert(c);
assert(u);
+ if (isempty(rvalue)) {
+ c->working_directory_home = false;
+ c->working_directory = mfree(c->working_directory);
+ return 0;
+ }
+
if (rvalue[0] == '-') {
missing_ok = true;
rvalue++;
@@ -2236,19 +2027,9 @@ int config_parse_working_directory(
return missing_ok ? 0 : -ENOEXEC;
}
- path_kill_slashes(k);
-
- if (!utf8_is_valid(k)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
- return missing_ok ? 0 : -ENOEXEC;
- }
-
- if (!path_is_absolute(k)) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Working directory path '%s' is not absolute%s.",
- rvalue, missing_ok ? ", ignoring" : "");
+ r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE | (missing_ok ? 0 : PATH_CHECK_FATAL), unit, filename, line, lvalue);
+ if (r < 0)
return missing_ok ? 0 : -ENOEXEC;
- }
c->working_directory_home = false;
free_and_replace(c->working_directory, k);
@@ -2287,19 +2068,20 @@ int config_parse_unit_env_file(const char *unit,
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);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
- if (!path_is_absolute(n[0] == '-' ? n + 1 : n)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Path '%s' is not absolute, ignoring.", n);
+ r = path_simplify_and_warn(n[0] == '-' ? n + 1 : n, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
return 0;
- }
- r = strv_extend(env, n);
+ r = strv_push(env, n);
if (r < 0)
return log_oom();
+ n = NULL;
+
return 0;
}
@@ -2349,13 +2131,11 @@ int config_parse_environ(
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers, ignoring: %s", word);
+ "Failed to resolve unit specifiers in %s, ignoring: %m", word);
continue;
}
- } else {
- k = word;
- word = NULL;
- }
+ } else
+ k = TAKE_PTR(word);
if (!env_assignment_is_valid(k)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -2383,10 +2163,10 @@ int config_parse_pass_environ(
void *data,
void *userdata) {
- const char *whole_rvalue = rvalue;
_cleanup_strv_free_ char **n = NULL;
size_t nlen = 0, nbufsize = 0;
char*** passenv = data;
+ const char *p = rvalue;
Unit *u = userdata;
int r;
@@ -2404,14 +2184,14 @@ int config_parse_pass_environ(
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
- r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Trailing garbage in %s, ignoring: %s", lvalue, whole_rvalue);
+ "Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
break;
}
@@ -2419,13 +2199,11 @@ int config_parse_pass_environ(
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers, ignoring: %s", word);
+ "Failed to resolve specifiers in %s, ignoring: %m", word);
continue;
}
- } else {
- k = word;
- word = NULL;
- }
+ } else
+ k = TAKE_PTR(word);
if (!env_name_is_valid(k)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -2436,9 +2214,8 @@ int config_parse_pass_environ(
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- n[nlen++] = k;
+ n[nlen++] = TAKE_PTR(k);
n[nlen] = NULL;
- k = NULL;
}
if (n) {
@@ -2463,9 +2240,9 @@ int config_parse_unset_environ(
void *userdata) {
_cleanup_strv_free_ char **n = NULL;
- const char *whole_rvalue = rvalue;
size_t nlen = 0, nbufsize = 0;
char*** unsetenv = data;
+ const char *p = rvalue;
Unit *u = userdata;
int r;
@@ -2483,14 +2260,14 @@ int config_parse_unset_environ(
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
- r = extract_first_word(&rvalue, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Trailing garbage in %s, ignoring: %s", lvalue, whole_rvalue);
+ "Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
break;
}
@@ -2498,13 +2275,11 @@ int config_parse_unset_environ(
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers, ignoring: %s", word);
+ "Failed to resolve unit specifiers in %s, ignoring: %m", word);
continue;
}
- } else {
- k = word;
- word = NULL;
- }
+ } else
+ k = TAKE_PTR(word);
if (!env_assignment_is_valid(k) && !env_name_is_valid(k)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -2515,9 +2290,8 @@ int config_parse_unset_environ(
if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
return log_oom();
- n[nlen++] = k;
+ n[nlen++] = TAKE_PTR(k);
n[nlen] = NULL;
- k = NULL;
}
if (n) {
@@ -2543,7 +2317,7 @@ int config_parse_log_extra_fields(
ExecContext *c = data;
Unit *u = userdata;
- const char *p;
+ const char *p = rvalue;
int r;
assert(filename);
@@ -2556,14 +2330,14 @@ int config_parse_log_extra_fields(
return 0;
}
- for (p = rvalue;; ) {
+ for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
struct iovec *t;
const char *eq;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_QUOTES);
if (r == 0)
- break;
+ return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2573,18 +2347,18 @@ int config_parse_log_extra_fields(
r = unit_full_printf(u, word, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring field: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word);
continue;
}
eq = strchr(k, '=');
if (!eq) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Log field lacks '=' character, ignoring field: %s", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Log field lacks '=' character, ignoring: %s", k);
continue;
}
if (!journal_field_valid(k, eq-k, false)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Log field name is invalid, ignoring field: %s", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Log field name is invalid, ignoring: %s", k);
continue;
}
@@ -2597,36 +2371,6 @@ int config_parse_log_extra_fields(
k = NULL;
}
-
- return 0;
-}
-
-int config_parse_ip_tos(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *ip_tos = data, x;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- x = ip_tos_from_string(rvalue);
- if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IP TOS value, ignoring: %s", rvalue);
- return 0;
- }
-
- *ip_tos = x;
- return 0;
}
int config_parse_unit_condition_path(
@@ -2669,14 +2413,13 @@ int config_parse_unit_condition_path(
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);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
- if (!path_is_absolute(p)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Path in condition not absolute, ignoring: %s", p);
+ r = path_simplify_and_warn(p, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
return 0;
- }
c = condition_new(t, p, trigger, negate);
if (!c)
@@ -2726,7 +2469,7 @@ int config_parse_unit_condition_string(
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);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
@@ -2790,9 +2533,6 @@ int config_parse_unit_condition_null(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_emergency_action, emergency_action, EmergencyAction, "Failed to parse failure action specifier");
-
int config_parse_unit_requires_mounts_for(
const char *unit,
const char *filename,
@@ -2805,8 +2545,8 @@ int config_parse_unit_requires_mounts_for(
void *data,
void *userdata) {
+ const char *p = rvalue;
Unit *u = userdata;
- const char *p;
int r;
assert(filename);
@@ -2814,7 +2554,7 @@ int config_parse_unit_requires_mounts_for(
assert(rvalue);
assert(data);
- for (p = rvalue;; ) {
+ for (;;) {
_cleanup_free_ char *word = NULL, *resolved = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
@@ -2828,20 +2568,19 @@ int config_parse_unit_requires_mounts_for(
return 0;
}
- if (!utf8_is_valid(word)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
- continue;
- }
-
r = unit_full_printf(u, word, &resolved);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit name \"%s\", ignoring: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
continue;
}
+ r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
+ continue;
+
r = unit_require_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", resolved);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount '%s', ignoring: %m", resolved);
continue;
}
}
@@ -2955,12 +2694,12 @@ int config_parse_syscall_filter(
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
- break;
+ return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
- break;
+ return 0;
}
r = parse_syscall_and_errno(word, &name, &num);
@@ -2975,8 +2714,6 @@ int config_parse_syscall_filter(
if (r < 0)
return r;
}
-
- return 0;
}
int config_parse_syscall_archs(
@@ -2991,8 +2728,8 @@ int config_parse_syscall_archs(
void *data,
void *userdata) {
+ const char *p = rvalue;
Set **archs = data;
- const char *p;
int r;
if (isempty(rvalue)) {
@@ -3004,7 +2741,7 @@ int config_parse_syscall_archs(
if (r < 0)
return log_oom();
- for (p = rvalue;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL;
uint32_t a;
@@ -3124,9 +2861,9 @@ int config_parse_address_families(
}
af = af_from_name(word);
- if (af <= 0) {
+ if (af <= 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
- "Failed to parse address family \"%s\", ignoring: %m", word);
+ "Failed to parse address family, ignoring: %s", word);
continue;
}
@@ -3155,11 +2892,22 @@ int config_parse_restrict_namespaces(
void *userdata) {
ExecContext *c = data;
+ unsigned long flags;
bool invert = false;
int r;
if (isempty(rvalue)) {
/* Reset to the default. */
+ c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL;
+ return 0;
+ }
+
+ /* Boolean parameter ignores the previous settings */
+ r = parse_boolean(rvalue);
+ if (r > 0) {
+ c->restrict_namespaces = 0;
+ return 0;
+ } else if (r == 0) {
c->restrict_namespaces = NAMESPACE_FLAGS_ALL;
return 0;
}
@@ -3169,23 +2917,19 @@ int config_parse_restrict_namespaces(
rvalue++;
}
- r = parse_boolean(rvalue);
- if (r > 0)
- c->restrict_namespaces = 0;
- else if (r == 0)
- c->restrict_namespaces = NAMESPACE_FLAGS_ALL;
- else {
- /* Not a boolean argument, in this case it's a list of namespace types. */
-
- r = namespace_flag_from_string_many(rvalue, &c->restrict_namespaces);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse namespace type string, ignoring: %s", rvalue);
- return 0;
- }
+ /* Not a boolean argument, in this case it's a list of namespace types. */
+ r = namespace_flags_from_string(rvalue, &flags);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse namespace type string, ignoring: %s", rvalue);
+ return 0;
}
- if (invert)
- c->restrict_namespaces = (~c->restrict_namespaces) & NAMESPACE_FLAGS_ALL;
+ if (c->restrict_namespaces == NAMESPACE_FLAGS_INITIAL)
+ /* Initial assignment. Just set the value. */
+ c->restrict_namespaces = invert ? (~flags) & NAMESPACE_FLAGS_ALL : flags;
+ else
+ /* Merge the value with the previous one. */
+ SET_FLAG(c->restrict_namespaces, flags, !invert);
return 0;
}
@@ -3203,6 +2947,7 @@ int config_parse_unit_slice(
void *data,
void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *k = NULL;
Unit *u = userdata, *slice = NULL;
int r;
@@ -3214,77 +2959,19 @@ int config_parse_unit_slice(
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);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
- r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
+ r = manager_load_unit(u->manager, k, NULL, &error, &slice);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load slice unit %s. Ignoring.", k);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load slice unit %s, ignoring: %s", k, bus_error_message(&error, r));
return 0;
}
r = unit_set_slice(u, slice);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to assign slice %s to unit %s. Ignoring.", slice->id, u->id);
- return 0;
- }
-
- return 0;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
-
-int config_parse_cpu_weight(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *weight = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = cg_weight_parse(rvalue, weight);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "CPU weight '%s' invalid. Ignoring.", rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_cpu_shares(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *shares = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = cg_cpu_shares_parse(rvalue, shares);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "CPU shares '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to assign slice %s to unit %s, ignoring: %m", slice->id, u->id);
return 0;
}
@@ -3317,7 +3004,7 @@ int config_parse_cpu_quota(
r = parse_percent_unbounded(rvalue);
if (r <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "CPU quota '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU quota '%s', ignoring.", rvalue);
return 0;
}
@@ -3347,14 +3034,15 @@ int config_parse_memory_limit(
if (r < 0) {
r = parse_size(rvalue, 1024, &bytes);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Memory limit '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid memory limit '%s', ignoring: %m", rvalue);
return 0;
}
} else
bytes = physical_memory_scale(r, 100U);
- if (bytes <= 0 || bytes >= UINT64_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range. Ignoring.", rvalue);
+ if (bytes >= UINT64_MAX ||
+ (bytes <= 0 && !streq(lvalue, "MemorySwapMax"))) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue);
return 0;
}
}
@@ -3405,14 +3093,14 @@ int config_parse_tasks_max(
if (r < 0) {
r = safe_atou64(rvalue, &v);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid maximum tasks value '%s', ignoring: %m", rvalue);
return 0;
}
} else
v = system_tasks_max_scale(r, 100U);
if (v <= 0 || v >= UINT64_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue);
return 0;
}
@@ -3433,13 +3121,23 @@ int config_parse_delegate(
void *userdata) {
CGroupContext *c = data;
+ UnitType t;
int r;
+ t = unit_name_to_type(unit);
+ assert(t != _UNIT_TYPE_INVALID);
+
+ if (!unit_vtable[t]->can_delegate) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Delegate= setting not supported for this unit type, ignoring.");
+ return 0;
+ }
+
/* We either accept a boolean value, which may be used to turn on delegation for all controllers, or turn it
* off for all. Or it takes a list of controller names, in which case we add the specified controllers to the
* mask to delegate. */
if (isempty(rvalue)) {
+ /* An empty string resets controllers and set Delegate=yes. */
c->delegate = true;
c->delegate_controllers = 0;
return 0;
@@ -3461,12 +3159,12 @@ int config_parse_delegate(
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
- return r;
+ return 0;
}
cc = cgroup_controller_from_string(word);
if (cc < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid controller name '%s', ignoring", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid controller name '%s', ignoring", word);
continue;
}
@@ -3499,11 +3197,10 @@ int config_parse_device_allow(
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL, *t = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupContext *c = data;
CGroupDeviceAllow *a;
- const char *m = NULL;
- size_t n;
+ const char *p = rvalue;
int r;
if (isempty(rvalue)) {
@@ -3513,31 +3210,41 @@ int config_parse_device_allow(
return 0;
}
- r = unit_full_printf(userdata, rvalue, &t);
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to resolve specifiers in %s, ignoring: %m",
- rvalue);
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device path and rights from '%s', ignoring.", rvalue);
+ return 0;
}
- n = strcspn(t, WHITESPACE);
-
- path = strndup(t, n);
- if (!path)
- return log_oom();
-
- if (!is_deviceallow_pattern(path) &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
return 0;
}
- m = t + n + strspn(t + n, WHITESPACE);
- if (isempty(m))
- m = "rwm";
+ if (!startswith(resolved, "block-") && !startswith(resolved, "char-")) {
+
+ r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
+ if (r < 0)
+ return 0;
+
+ if (!valid_device_node_path(resolved)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved);
+ return 0;
+ }
+ }
- if (!in_charset(m, "rwm")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s'. Ignoring.", m);
+ if (!isempty(p) && !in_charset(p, "rwm")) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s', ignoring.", p);
return 0;
}
@@ -3545,44 +3252,15 @@ int config_parse_device_allow(
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');
+ a->path = TAKE_PTR(resolved);
+ a->r = isempty(p) || !!strchr(p, 'r');
+ a->w = isempty(p) || !!strchr(p, 'w');
+ a->m = isempty(p) || !!strchr(p, 'm');
LIST_PREPEND(device_allow, c->device_allow, a);
return 0;
}
-int config_parse_io_weight(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *weight = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = cg_weight_parse(rvalue, weight);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid. Ignoring.", rvalue);
- return 0;
- }
-
- return 0;
-}
-
int config_parse_io_device_weight(
const char *unit,
const char *filename,
@@ -3595,12 +3273,11 @@ int config_parse_io_device_weight(
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupIODeviceWeight *w;
CGroupContext *c = data;
- const char *weight;
+ const char *p = rvalue;
uint64_t u;
- size_t n;
int r;
assert(filename);
@@ -3614,28 +3291,34 @@ int config_parse_io_device_weight(
return 0;
}
- n = strcspn(rvalue, WHITESPACE);
- weight = rvalue + n;
- weight += strspn(weight, WHITESPACE);
-
- if (isempty(weight)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Expected block device and device weight. Ignoring.");
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0 || isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device path and weight from '%s', ignoring.", rvalue);
return 0;
}
- path = strndup(rvalue, n);
- if (!path)
- return log_oom();
-
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
return 0;
}
- r = cg_weight_parse(weight, &u);
+ r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
+ if (r < 0)
+ return 0;
+
+ r = cg_weight_parse(p, &u);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid. Ignoring.", weight);
+ log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid, ignoring: %m", p);
return 0;
}
@@ -3645,9 +3328,7 @@ int config_parse_io_device_weight(
if (!w)
return log_oom();
- w->path = path;
- path = NULL;
-
+ w->path = TAKE_PTR(resolved);
w->weight = u;
LIST_PREPEND(device_weights, c->io_device_weights, w);
@@ -3666,13 +3347,12 @@ int config_parse_io_limit(
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupIODeviceLimit *l = NULL, *t;
CGroupContext *c = data;
CGroupIOLimitType type;
- const char *limit;
+ const char *p = rvalue;
uint64_t num;
- size_t n;
int r;
assert(filename);
@@ -3688,37 +3368,43 @@ int config_parse_io_limit(
return 0;
}
- n = strcspn(rvalue, WHITESPACE);
- limit = rvalue + n;
- limit += strspn(limit, WHITESPACE);
-
- if (!*limit) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Expected space separated pair of device node and bandwidth. Ignoring.");
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0 || isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device node and bandwidth from '%s', ignoring.", rvalue);
return 0;
}
- path = strndup(rvalue, n);
- if (!path)
- return log_oom();
-
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
return 0;
}
- if (streq("infinity", limit)) {
+ r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
+ if (r < 0)
+ return 0;
+
+ if (streq("infinity", p))
num = CGROUP_LIMIT_MAX;
- } else {
- r = parse_size(limit, 1000, &num);
+ else {
+ r = parse_size(p, 1000, &num);
if (r < 0 || num <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "IO Limit '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid IO limit '%s', ignoring.", p);
return 0;
}
}
LIST_FOREACH(device_limits, t, c->io_device_limits) {
- if (path_equal(path, t->path)) {
+ if (path_equal(resolved, t->path)) {
l = t;
break;
}
@@ -3731,8 +3417,7 @@ int config_parse_io_limit(
if (!l)
return log_oom();
- l->path = path;
- path = NULL;
+ l->path = TAKE_PTR(resolved);
for (ttype = 0; ttype < _CGROUP_IO_LIMIT_TYPE_MAX; ttype++)
l->limits[ttype] = cgroup_io_limit_defaults[ttype];
@@ -3744,34 +3429,6 @@ int config_parse_io_limit(
return 0;
}
-int config_parse_blockio_weight(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *weight = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = cg_blkio_weight_parse(rvalue, weight);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", rvalue);
- return 0;
- }
-
- return 0;
-}
-
int config_parse_blockio_device_weight(
const char *unit,
const char *filename,
@@ -3784,12 +3441,11 @@ int config_parse_blockio_device_weight(
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupBlockIODeviceWeight *w;
CGroupContext *c = data;
- const char *weight;
+ const char *p = rvalue;
uint64_t u;
- size_t n;
int r;
assert(filename);
@@ -3803,28 +3459,34 @@ int config_parse_blockio_device_weight(
return 0;
}
- n = strcspn(rvalue, WHITESPACE);
- weight = rvalue + n;
- weight += strspn(weight, WHITESPACE);
-
- if (isempty(weight)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Expected block device and device weight. Ignoring.");
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0 || isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device node and weight from '%s', ignoring.", rvalue);
return 0;
}
- path = strndup(rvalue, n);
- if (!path)
- return log_oom();
-
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
return 0;
}
- r = cg_blkio_weight_parse(weight, &u);
+ r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
+ if (r < 0)
+ return 0;
+
+ r = cg_blkio_weight_parse(p, &u);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", weight);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid block IO weight '%s', ignoring: %m", p);
return 0;
}
@@ -3834,9 +3496,7 @@ int config_parse_blockio_device_weight(
if (!w)
return log_oom();
- w->path = path;
- path = NULL;
-
+ w->path = TAKE_PTR(resolved);
w->weight = u;
LIST_PREPEND(device_weights, c->blockio_device_weights, w);
@@ -3855,13 +3515,12 @@ int config_parse_blockio_bandwidth(
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupBlockIODeviceBandwidth *b = NULL, *t;
CGroupContext *c = data;
- const char *bandwidth;
+ const char *p = rvalue;
uint64_t bytes;
bool read;
- size_t n;
int r;
assert(filename);
@@ -3878,33 +3537,39 @@ int config_parse_blockio_bandwidth(
return 0;
}
- n = strcspn(rvalue, WHITESPACE);
- bandwidth = rvalue + n;
- bandwidth += strspn(bandwidth, WHITESPACE);
-
- if (!*bandwidth) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Expected space separated pair of device node and bandwidth. Ignoring.");
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0 || isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device node and bandwidth from '%s', ignoring.", rvalue);
return 0;
}
- path = strndup(rvalue, n);
- if (!path)
- return log_oom();
-
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
return 0;
}
- r = parse_size(bandwidth, 1000, &bytes);
+ r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue);
+ if (r < 0)
+ return 0;
+
+ r = parse_size(p, 1000, &bytes);
if (r < 0 || bytes <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid Block IO Bandwidth '%s', ignoring.", p);
return 0;
}
LIST_FOREACH(device_bandwidths, t, c->blockio_device_bandwidths) {
- if (path_equal(path, t->path)) {
+ if (path_equal(resolved, t->path)) {
b = t;
break;
}
@@ -3915,8 +3580,7 @@ int config_parse_blockio_bandwidth(
if (!b)
return log_oom();
- b->path = path;
- path = NULL;
+ b->path = TAKE_PTR(resolved);
b->rbps = CGROUP_LIMIT_MAX;
b->wbps = CGROUP_LIMIT_MAX;
@@ -3931,8 +3595,6 @@ int config_parse_blockio_bandwidth(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
-
int config_parse_job_mode_isolate(
const char *unit,
const char *filename,
@@ -3964,8 +3626,6 @@ int config_parse_job_mode_isolate(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
-
int config_parse_exec_directories(
const char *unit,
const char *filename,
@@ -4011,13 +3671,17 @@ int config_parse_exec_directories(
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers in \"%s\", ignoring: %m", word);
+ "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word);
continue;
}
- if (!path_is_normalized(k) || path_is_absolute(k)) {
+ r = path_simplify_and_warn(k, PATH_CHECK_RELATIVE, unit, filename, line, lvalue);
+ if (r < 0)
+ continue;
+
+ if (path_startswith(k, "private")) {
log_syntax(unit, LOG_ERR, filename, line, 0,
- "%s= path is not valid, ignoring assignment: %s", lvalue, rvalue);
+ "%s= path can't be 'private', ingoring assignment: %s", lvalue, word);
continue;
}
@@ -4067,7 +3731,7 @@ int config_parse_set_status(
r = safe_atoi(temp, &val);
if (r < 0) {
- val = signal_from_string_try_harder(temp);
+ val = signal_from_string(temp);
if (val <= 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse value, ignoring: %s", word);
@@ -4087,10 +3751,8 @@ int config_parse_set_status(
return log_oom();
r = set_put(*set, INT_TO_PTR(val));
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Unable to store: %s", word);
- return r;
- }
+ if (r < 0)
+ return log_oom();
}
if (!isempty(state))
log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
@@ -4112,7 +3774,7 @@ int config_parse_namespace_path_strv(
Unit *u = userdata;
char*** sv = data;
- const char *cur;
+ const char *p = rvalue;
int r;
assert(filename);
@@ -4126,13 +3788,12 @@ int config_parse_namespace_path_strv(
return 0;
}
- cur = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL, *resolved = NULL, *joined = NULL;
const char *w;
bool ignore_enoent = false, shall_prefix = false;
- r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)
@@ -4142,11 +3803,6 @@ int config_parse_namespace_path_strv(
return 0;
}
- if (!utf8_is_valid(word)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word);
- continue;
- }
-
w = word;
if (startswith(w, "-")) {
ignore_enoent = true;
@@ -4159,16 +3815,13 @@ int config_parse_namespace_path_strv(
r = unit_full_printf(u, w, &resolved);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers in %s: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w);
continue;
}
- if (!path_is_absolute(resolved)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", resolved);
+ r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
continue;
- }
-
- path_kill_slashes(resolved);
joined = strjoin(ignore_enoent ? "-" : "",
shall_prefix ? "+" : "",
@@ -4198,7 +3851,7 @@ int config_parse_temporary_filesystems(
Unit *u = userdata;
ExecContext *c = data;
- const char *cur;
+ const char *p = rvalue;
int r;
assert(filename);
@@ -4214,14 +3867,13 @@ int config_parse_temporary_filesystems(
return 0;
}
- cur = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL, *path = NULL, *resolved = NULL;
const char *w;
- r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
- break;
+ return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -4231,23 +3883,26 @@ int config_parse_temporary_filesystems(
w = word;
r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- r = unit_full_printf(u, path, &resolved);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers in %s, ignoring: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", word);
+ continue;
+ }
+ if (r == 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring: %s", word);
continue;
}
- if (!path_is_absolute(resolved)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", resolved);
+ r = unit_full_printf(u, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path);
continue;
}
- path_kill_slashes(resolved);
+ r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
+ continue;
r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, path, w);
if (r == -ENOMEM)
@@ -4257,8 +3912,6 @@ int config_parse_temporary_filesystems(
continue;
}
}
-
- return 0;
}
int config_parse_bind_paths(
@@ -4304,15 +3957,15 @@ int config_parse_bind_paths(
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s: %s", lvalue, rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
return 0;
}
r = unit_full_printf(u, source, &sresolved);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolved specifiers in \"%s\", ignoring: %m", source);
- return 0;
+ "Failed to resolved unit specifiers in \"%s\", ignoring: %m", source);
+ continue;
}
s = sresolved;
@@ -4321,16 +3974,9 @@ int config_parse_bind_paths(
s++;
}
- if (!utf8_is_valid(s)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, s);
- return 0;
- }
- if (!path_is_absolute(s)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute source path, ignoring: %s", s);
- return 0;
- }
-
- path_kill_slashes(s);
+ r = path_simplify_and_warn(s, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
+ continue;
/* Optionally, the destination is specified. */
if (p && p[-1] == ':') {
@@ -4338,31 +3984,26 @@ int config_parse_bind_paths(
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s: %s", lvalue, rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
return 0;
}
if (r == 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Missing argument after ':': %s", rvalue);
- return 0;
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Missing argument after ':', ignoring: %s", s);
+ continue;
}
r = unit_full_printf(u, destination, &dresolved);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to resolved specifiers in \"%s\", ignoring: %m", destination);
- return 0;
+ continue;
}
- if (!utf8_is_valid(dresolved)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, dresolved);
- return 0;
- }
- if (!path_is_absolute(dresolved)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute destination path, ignoring: %s", dresolved);
- return 0;
- }
+ r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+ if (r < 0)
+ continue;
- d = path_kill_slashes(dresolved);
+ d = dresolved;
/* Optionally, there's also a short option string specified */
if (p && p[-1] == ':') {
@@ -4382,7 +4023,7 @@ int config_parse_bind_paths(
rbind = false;
else {
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid option string, ignoring setting: %s", options);
- return 0;
+ continue;
}
}
} else
@@ -4403,107 +4044,6 @@ int config_parse_bind_paths(
return 0;
}
-int config_parse_no_new_privileges(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int k;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- k = parse_boolean(rvalue);
- if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
- return 0;
- }
-
- c->no_new_privileges = k;
-
- return 0;
-}
-
-int config_parse_protect_home(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- ProtectHome h;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- /* Our enum shall be a superset of booleans, hence first try
- * to parse as boolean, and then as enum */
-
- h = parse_protect_home_or_bool(rvalue);
- if (h < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue);
- return 0;
- }
-
- c->protect_home = h;
-
- return 0;
-}
-
-int config_parse_protect_system(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- ProtectSystem s;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- /* Our enum shall be a superset of booleans, hence first try
- * to parse as boolean, and then as enum */
-
- s = parse_protect_system_or_bool(rvalue);
- if (s < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
- return 0;
- }
-
- c->protect_system = s;
-
- return 0;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode");
-
int config_parse_job_timeout_sec(
const char* unit,
const char *filename,
@@ -4598,7 +4138,7 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
if (c++ >= FOLLOW_MAX)
return -ELOOP;
- path_kill_slashes(*filename);
+ path_simplify(*filename, false);
/* Add the file name we are currently looking at to
* the names of this unit, but only if it is a valid
@@ -4631,8 +4171,7 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
if (r < 0)
return r;
- free(*filename);
- *filename = target;
+ free_and_replace(*filename, target);
}
f = fdopen(fd, "re");
@@ -4806,9 +4345,7 @@ static int load_from_path(Unit *u, const char *path) {
return r;
}
- free(u->fragment_path);
- u->fragment_path = filename;
- filename = NULL;
+ free_and_replace(u->fragment_path, filename);
if (u->source_path) {
if (stat(u->source_path, &st) >= 0)
@@ -4915,9 +4452,7 @@ void unit_dump_config_items(FILE *f) {
const ConfigParserCallback callback;
const char *rvalue;
} table[] = {
-#if !HAVE_SYSV_COMPAT || !HAVE_SECCOMP || !HAVE_PAM || !HAVE_SELINUX || !ENABLE_SMACK || !HAVE_APPARMOR
{ config_parse_warn_compat, "NOTSUPPORTED" },
-#endif
{ config_parse_int, "INTEGER" },
{ config_parse_unsigned, "UNSIGNED" },
{ config_parse_iec_size, "SIZE" },
@@ -4943,14 +4478,11 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_log_level, "LEVEL" },
{ config_parse_exec_secure_bits, "SECUREBITS" },
{ config_parse_capability_set, "BOUNDINGSET" },
- { config_parse_limit, "LIMIT" },
+ { config_parse_rlimit, "LIMIT" },
{ config_parse_unit_deps, "UNIT [...]" },
{ config_parse_exec, "PATH [ARGUMENT [...]]" },
{ config_parse_service_type, "SERVICETYPE" },
{ config_parse_service_restart, "SERVICERESTART" },
-#if HAVE_SYSV_COMPAT
- { config_parse_sysv_priority, "SYSVPRIORITY" },
-#endif
{ config_parse_kill_mode, "KILLMODE" },
{ config_parse_signal, "SIGNAL" },
{ config_parse_socket_listen, "SOCKET [...]" },
@@ -4986,12 +4518,11 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_restrict_namespaces, "NAMESPACES" },
#endif
{ config_parse_cpu_shares, "SHARES" },
- { config_parse_cpu_weight, "WEIGHT" },
+ { config_parse_cg_weight, "WEIGHT" },
{ config_parse_memory_limit, "LIMIT" },
{ config_parse_device_allow, "DEVICE" },
{ config_parse_device_policy, "POLICY" },
{ config_parse_io_limit, "LIMIT" },
- { config_parse_io_weight, "WEIGHT" },
{ config_parse_io_device_weight, "DEVICEWEIGHT" },
{ config_parse_blockio_bandwidth, "BANDWIDTH" },
{ config_parse_blockio_weight, "WEIGHT" },
@@ -5013,13 +4544,24 @@ void unit_dump_config_items(FILE *f) {
NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
const char *rvalue = "OTHER", *lvalue;
- unsigned j;
+ const ConfigPerfItem *p;
size_t prefix_len;
const char *dot;
- const ConfigPerfItem *p;
+ unsigned j;
assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
+ /* Hide legacy settings */
+ if (p->parse == config_parse_warn_compat &&
+ p->ltype == DISABLED_LEGACY)
+ continue;
+
+ for (j = 0; j < ELEMENTSOF(table); j++)
+ if (p->parse == table[j].callback) {
+ rvalue = table[j].rvalue;
+ break;
+ }
+
dot = strchr(i, '.');
lvalue = dot ? dot + 1 : i;
prefix_len = dot-i;
@@ -5032,12 +4574,6 @@ void unit_dump_config_items(FILE *f) {
fprintf(f, "[%.*s]\n", (int) prefix_len, i);
}
- for (j = 0; j < ELEMENTSOF(table); j++)
- if (p->parse == table[j].callback) {
- rvalue = table[j].rvalue;
- break;
- }
-
fprintf(f, "%s=%s\n", lvalue, rvalue);
prev = i;
}
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 163b5ce485..dad281ef72 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -1,25 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
+#include "conf-parser.h"
#include "unit.h"
/* Read service data from .desktop file style configuration fragments */
@@ -28,110 +10,99 @@ int unit_load_fragment(Unit *u);
void unit_dump_config_items(FILE *f);
-int config_parse_warn_compat(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_deps(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_obsolete_unit_deps(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_string_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_strv_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_path_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_path_strv_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_documentation(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_listen(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_protocol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_bind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_nice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_oom_score_adjust(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_timeout(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_restart(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_bindtodevice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_output(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_input(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_input_text(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_input_data(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_io_class(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_io_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_sched_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_sched_prio(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_affinity(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_secure_bits(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_capability_set(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_sysv_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_kill_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_mount_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_timer(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_trigger_unit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path_spec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_service(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_sockets(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_env_file(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ip_tos(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_path(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_string(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_null(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_kill_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_notify_access(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_emergency_action(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_requires_mounts_for(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_filter(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_archs(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_errno(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_pass_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unset_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_slice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_cpu_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_delegate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_io_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_io_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_io_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_blockio_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_netclass(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_job_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_job_mode_isolate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_selinux_context(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_apparmor_profile(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_smack_process_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_families(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_runtime_preserve_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_directories(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_set_status(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_namespace_path_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_temporary_filesystems(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_no_new_privileges(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_cpu_quota(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_protect_home(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_protect_system(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bus_name(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_utmp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_working_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_fdname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_sec_fix_0(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_user_group(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_user_group_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_restrict_namespaces(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bind_paths(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_keyring_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_job_timeout_sec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_job_running_timeout_sec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_log_extra_fields(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_collect_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_deps);
+CONFIG_PARSER_PROTOTYPE(config_parse_obsolete_unit_deps);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_string_printf);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_strv_printf);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_printf);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_strv_printf);
+CONFIG_PARSER_PROTOTYPE(config_parse_documentation);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_listen);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_bind);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_nice);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_oom_score_adjust);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_restart);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_bindtodevice);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_output);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_input);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_input_text);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_input_data);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_io_class);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_io_priority);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_policy);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
+CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
+CONFIG_PARSER_PROTOTYPE(config_parse_kill_signal);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_flags);
+CONFIG_PARSER_PROTOTYPE(config_parse_timer);
+CONFIG_PARSER_PROTOTYPE(config_parse_trigger_unit);
+CONFIG_PARSER_PROTOTYPE(config_parse_path_spec);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_service);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_sockets);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_env_file);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_tos);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_path);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_string);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_null);
+CONFIG_PARSER_PROTOTYPE(config_parse_kill_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_notify_access);
+CONFIG_PARSER_PROTOTYPE(config_parse_emergency_action);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_requires_mounts_for);
+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_archs);
+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_errno);
+CONFIG_PARSER_PROTOTYPE(config_parse_environ);
+CONFIG_PARSER_PROTOTYPE(config_parse_pass_environ);
+CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_slice);
+CONFIG_PARSER_PROTOTYPE(config_parse_cg_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_cpu_shares);
+CONFIG_PARSER_PROTOTYPE(config_parse_memory_limit);
+CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
+CONFIG_PARSER_PROTOTYPE(config_parse_delegate);
+CONFIG_PARSER_PROTOTYPE(config_parse_device_policy);
+CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
+CONFIG_PARSER_PROTOTYPE(config_parse_io_device_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_io_limit);
+CONFIG_PARSER_PROTOTYPE(config_parse_blockio_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_blockio_device_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_blockio_bandwidth);
+CONFIG_PARSER_PROTOTYPE(config_parse_netclass);
+CONFIG_PARSER_PROTOTYPE(config_parse_job_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_job_mode_isolate);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_selinux_context);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_apparmor_profile);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_smack_process_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_families);
+CONFIG_PARSER_PROTOTYPE(config_parse_runtime_preserve_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_directories);
+CONFIG_PARSER_PROTOTYPE(config_parse_set_status);
+CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems);
+CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
+CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
+CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
+CONFIG_PARSER_PROTOTYPE(config_parse_bus_name);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_utmp_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_working_directory);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdname);
+CONFIG_PARSER_PROTOTYPE(config_parse_sec_fix_0);
+CONFIG_PARSER_PROTOTYPE(config_parse_user_group);
+CONFIG_PARSER_PROTOTYPE(config_parse_user_group_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_restrict_namespaces);
+CONFIG_PARSER_PROTOTYPE(config_parse_bind_paths);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_keyring_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_job_timeout_sec);
+CONFIG_PARSER_PROTOTYPE(config_parse_job_running_timeout_sec);
+CONFIG_PARSER_PROTOTYPE(config_parse_log_extra_fields);
+CONFIG_PARSER_PROTOTYPE(config_parse_collect_mode);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
extern const char load_fragment_gperf_nulstr[];
-
-typedef enum Disabled {
- DISABLED_CONFIGURATION,
- DISABLED_LEGACY,
- DISABLED_EXPERIMENTAL,
-} Disabled;
diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c
index 0c43cf2418..c14523fee9 100644
--- a/src/core/locale-setup.c
+++ b/src/core/locale-setup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
@@ -37,7 +19,7 @@ int locale_setup(char ***environment) {
int r = 0, i;
if (detect_container() <= 0) {
- r = parse_env_file("/proc/cmdline", WHITESPACE,
+ r = parse_env_file(NULL, "/proc/cmdline", WHITESPACE,
"locale.LANG", &variables[VARIABLE_LANG],
"locale.LANGUAGE", &variables[VARIABLE_LANGUAGE],
"locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
@@ -61,7 +43,7 @@ int locale_setup(char ***environment) {
/* Hmm, nothing set on the kernel cmd line? Then let's
* try /etc/locale.conf */
if (r <= 0) {
- r = parse_env_file("/etc/locale.conf", NEWLINE,
+ r = parse_env_file(NULL, "/etc/locale.conf", NEWLINE,
"LANG", &variables[VARIABLE_LANG],
"LANGUAGE", &variables[VARIABLE_LANGUAGE],
"LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
@@ -110,8 +92,7 @@ int locale_setup(char ***environment) {
goto finish;
}
- strv_free(*environment);
- *environment = e;
+ strv_free_and_replace(*environment, e);
}
r = 0;
diff --git a/src/core/locale-setup.h b/src/core/locale-setup.h
index c1bee3812b..01fadd06c7 100644
--- a/src/core/locale-setup.h
+++ b/src/core/locale-setup.h
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int locale_setup(char ***environment);
diff --git a/src/core/loopback-setup.c b/src/core/loopback-setup.c
index 1528034e81..835553ec8f 100644
--- a/src/core/loopback-setup.c
+++ b/src/core/loopback-setup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
#include <stdlib.h>
diff --git a/src/core/loopback-setup.h b/src/core/loopback-setup.h
index 9fac0189e4..c0eea100ed 100644
--- a/src/core/loopback-setup.h
+++ b/src/core/loopback-setup.h
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int loopback_setup(void);
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index 1b7424800c..11528f83c4 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <sched.h>
diff --git a/src/core/machine-id-setup.h b/src/core/machine-id-setup.h
index cbd83ba270..d6ac62a882 100644
--- a/src/core/machine-id-setup.h
+++ b/src/core/machine-id-setup.h
@@ -1,24 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int machine_id_commit(const char *root);
int machine_id_setup(const char *root, sd_id128_t requested, sd_id128_t *ret);
diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in
index 6a162a0ec8..f3b74f4273 100644
--- a/src/core/macros.systemd.in
+++ b/src/core/macros.systemd.in
@@ -4,19 +4,6 @@
# This file is part of systemd.
#
# Copyright 2012 Lennart Poettering
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
# RPM macros for packages installing systemd unit files
@@ -27,10 +14,13 @@
%_udevhwdbdir @udevhwdbdir@
%_udevrulesdir @udevrulesdir@
%_journalcatalogdir @catalogdir@
-%_tmpfilesdir @tmpfilesdir@
-%_sysusersdir @sysusersdir@
-%_sysctldir @sysctldir@
%_binfmtdir @binfmtdir@
+%_sysctldir @sysctldir@
+%_sysusersdir @sysusersdir@
+%_tmpfilesdir @tmpfilesdir@
+%_environmnentdir @environmentdir@
+%_modulesloaddir @modulesloaddir@
+%_modprobedir @modprobedir@
%_systemdgeneratordir @systemgeneratordir@
%_systemdusergeneratordir @usergeneratordir@
%_systemd_system_env_generator_dir @systemenvgeneratordir@
@@ -51,23 +41,23 @@ OrderWithRequires(postun): systemd \
%systemd_post() \
if [ $1 -eq 1 ] ; then \
# Initial installation \
- systemctl --no-reload preset %{?*} >/dev/null 2>&1 || : \
+ systemctl --no-reload preset %{?*} &>/dev/null || : \
fi \
%{nil}
-%systemd_user_post() %{expand:%systemd_post \\--user \\--global %%{?*}}
+%systemd_user_post() %{expand:%systemd_post \\--global %%{?*}}
%systemd_preun() \
if [ $1 -eq 0 ] ; then \
# Package removal, not upgrade \
- systemctl --no-reload disable --now %{?*} > /dev/null 2>&1 || : \
+ systemctl --no-reload disable --now %{?*} &>/dev/null || : \
fi \
%{nil}
%systemd_user_preun() \
if [ $1 -eq 0 ] ; then \
# Package removal, not upgrade \
- systemctl --no-reload --user --global disable %{?*} > /dev/null 2>&1 || : \
+ systemctl --global disable %{?*} &>/dev/null || : \
fi \
%{nil}
@@ -78,7 +68,7 @@ fi \
%systemd_postun_with_restart() \
if [ $1 -ge 1 ] ; then \
# Package upgrade, not uninstall \
- systemctl try-restart %{?*} >/dev/null 2>&1 || : \
+ systemctl try-restart %{?*} &>/dev/null || : \
fi \
%{nil}
@@ -92,16 +82,16 @@ fi \
# Deprecated. Use %tmpfiles_create_package instead
%tmpfiles_create() \
-systemd-tmpfiles --create %{?*} >/dev/null 2>&1 || : \
+systemd-tmpfiles --create %{?*} &>/dev/null || : \
%{nil}
# Deprecated. Use %sysusers_create_package instead
%sysusers_create() \
-systemd-sysusers %{?*} >/dev/null 2>&1 || : \
+systemd-sysusers %{?*} &>/dev/null || : \
%{nil}
%sysusers_create_inline() \
-systemd-sysusers - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
+systemd-sysusers - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
%{?*} \
SYSTEMD_INLINE_EOF \
%{nil}
@@ -120,7 +110,7 @@ SYSTEMD_INLINE_EOF \
# %files
# %{_sysusersdir}/%{name}.conf
%sysusers_create_package() \
-systemd-sysusers --replace=%_sysusersdir/%1.conf - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
+systemd-sysusers --replace=%_sysusersdir/%1.conf - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
%(cat %2) \
SYSTEMD_INLINE_EOF \
%{nil}
@@ -139,15 +129,15 @@ SYSTEMD_INLINE_EOF \
# %files
# %{_tmpfilesdir}/%{name}.conf
%tmpfiles_create_package() \
-systemd-tmpfiles --replace=%_tmpfilesdir/%1.conf --create - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
+systemd-tmpfiles --replace=%_tmpfilesdir/%1.conf --create - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
%(cat %2) \
SYSTEMD_INLINE_EOF \
%{nil}
%sysctl_apply() \
-@rootlibexecdir@/systemd-sysctl %{?*} >/dev/null 2>&1 || : \
+@rootlibexecdir@/systemd-sysctl %{?*} &>/dev/null || : \
%{nil}
%binfmt_apply() \
-@rootlibexecdir@/systemd-binfmt %{?*} >/dev/null 2>&1 || : \
+@rootlibexecdir@/systemd-binfmt %{?*} &>/dev/null || : \
%{nil}
diff --git a/src/core/main.c b/src/core/main.c
index d6ae0c3602..9a4fc26425 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -49,10 +31,12 @@
#include "clock-util.h"
#include "conf-parser.h"
#include "cpu-set-util.h"
+#include "dbus.h"
#include "dbus-manager.h"
#include "def.h"
#include "emergency-action.h"
#include "env-util.h"
+#include "exit-status.h"
#include "fd-util.h"
#include "fdset.h"
#include "fileio.h"
@@ -69,6 +53,7 @@
#include "manager.h"
#include "missing.h"
#include "mount-setup.h"
+#include "os-util.h"
#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
@@ -100,7 +85,8 @@ static enum {
ACTION_HELP,
ACTION_VERSION,
ACTION_TEST,
- ACTION_DUMP_CONFIGURATION_ITEMS
+ ACTION_DUMP_CONFIGURATION_ITEMS,
+ ACTION_DUMP_BUS_PROPERTIES,
} arg_action = ACTION_RUN;
static char *arg_default_unit = NULL;
static bool arg_system = false;
@@ -127,6 +113,7 @@ static char *arg_watchdog_device = NULL;
static char **arg_default_environment = NULL;
static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
static uint64_t arg_capability_bounding_set = CAP_ALL;
+static bool arg_no_new_privs = false;
static nsec_t arg_timer_slack_nsec = NSEC_INFINITY;
static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;
static Set* arg_syscall_archs = NULL;
@@ -319,6 +306,7 @@ static int parse_confirm_spawn(const char *value, char **console) {
s = strjoin("/dev/", value);
if (!s)
return -ENOMEM;
+
*console = s;
return 0;
}
@@ -532,10 +520,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0; \
}
-DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level")
-DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target")
-DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" )
-DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location")
+DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level");
+DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target");
+DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" );
+DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location");
static int config_parse_cpu_affinity2(
const char *unit,
@@ -671,6 +659,7 @@ static int parse_config_file(void) {
{ "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
{ "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
{ "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
+ { "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
#if HAVE_SECCOMP
{ "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
#endif
@@ -685,22 +674,22 @@ static int parse_config_file(void) {
{ "Manager", "DefaultStartLimitIntervalSec",config_parse_sec, 0, &arg_default_start_limit_interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
- { "Manager", "DefaultLimitCPU", config_parse_limit, RLIMIT_CPU, arg_default_rlimit },
- { "Manager", "DefaultLimitFSIZE", config_parse_limit, RLIMIT_FSIZE, arg_default_rlimit },
- { "Manager", "DefaultLimitDATA", config_parse_limit, RLIMIT_DATA, arg_default_rlimit },
- { "Manager", "DefaultLimitSTACK", config_parse_limit, RLIMIT_STACK, arg_default_rlimit },
- { "Manager", "DefaultLimitCORE", config_parse_limit, RLIMIT_CORE, arg_default_rlimit },
- { "Manager", "DefaultLimitRSS", config_parse_limit, RLIMIT_RSS, arg_default_rlimit },
- { "Manager", "DefaultLimitNOFILE", config_parse_limit, RLIMIT_NOFILE, arg_default_rlimit },
- { "Manager", "DefaultLimitAS", config_parse_limit, RLIMIT_AS, arg_default_rlimit },
- { "Manager", "DefaultLimitNPROC", config_parse_limit, RLIMIT_NPROC, arg_default_rlimit },
- { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, RLIMIT_MEMLOCK, arg_default_rlimit },
- { "Manager", "DefaultLimitLOCKS", config_parse_limit, RLIMIT_LOCKS, arg_default_rlimit },
- { "Manager", "DefaultLimitSIGPENDING", config_parse_limit, RLIMIT_SIGPENDING, arg_default_rlimit },
- { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, RLIMIT_MSGQUEUE, arg_default_rlimit },
- { "Manager", "DefaultLimitNICE", config_parse_limit, RLIMIT_NICE, arg_default_rlimit },
- { "Manager", "DefaultLimitRTPRIO", config_parse_limit, RLIMIT_RTPRIO, arg_default_rlimit },
- { "Manager", "DefaultLimitRTTIME", config_parse_limit, RLIMIT_RTTIME, arg_default_rlimit },
+ { "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
+ { "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
+ { "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
+ { "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_default_rlimit },
+ { "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_default_rlimit },
+ { "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_default_rlimit },
+ { "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_default_rlimit },
+ { "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_default_rlimit },
+ { "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_default_rlimit },
+ { "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_default_rlimit },
+ { "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_default_rlimit },
+ { "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_default_rlimit },
+ { "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_default_rlimit },
+ { "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_default_rlimit },
+ { "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_default_rlimit },
+ { "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_default_rlimit },
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting },
{ "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_default_ip_accounting },
@@ -738,6 +727,10 @@ static void set_manager_defaults(Manager *m) {
assert(m);
+ /* Propagates the various default unit property settings into the manager object, i.e. properties that do not
+ * affect the manager itself, but are just what newly allocated units will have set if they haven't set
+ * anything else. (Also see set_manager_settings() for the settings that affect the manager's own behaviour) */
+
m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec;
m->default_std_output = arg_default_std_output;
m->default_std_error = arg_default_std_error;
@@ -762,6 +755,9 @@ static void set_manager_settings(Manager *m) {
assert(m);
+ /* Propagates the various manager settings into the manager object, i.e. properties that effect the manager
+ * itself (as opposed to just being inherited into newly allocated units, see set_manager_defaults() above). */
+
m->confirm_spawn = arg_confirm_spawn;
m->service_watchdogs = arg_service_watchdogs;
m->runtime_watchdog = arg_runtime_watchdog;
@@ -772,7 +768,6 @@ static void set_manager_settings(Manager *m) {
}
static int parse_argv(int argc, char *argv[]) {
-
enum {
ARG_LOG_LEVEL = 0x100,
ARG_LOG_TARGET,
@@ -785,6 +780,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_PAGER,
ARG_VERSION,
ARG_DUMP_CONFIGURATION_ITEMS,
+ ARG_DUMP_BUS_PROPERTIES,
ARG_DUMP_CORE,
ARG_CRASH_CHVT,
ARG_CRASH_SHELL,
@@ -812,6 +808,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
+ { "dump-bus-properties", no_argument, NULL, ARG_DUMP_BUS_PROPERTIES },
{ "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
{ "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT },
{ "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
@@ -931,6 +928,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
break;
+ case ARG_DUMP_BUS_PROPERTIES:
+ arg_action = ACTION_DUMP_BUS_PROPERTIES;
+ break;
+
case ARG_DUMP_CORE:
if (!optarg)
arg_dump_core = true;
@@ -1074,6 +1075,7 @@ static int help(void) {
" --test Determine startup sequence, dump it and exit\n"
" --no-pager Do not pipe output into a pager\n"
" --dump-configuration-items Dump understood unit configuration items\n"
+ " --dump-bus-properties Dump exposed bus properties\n"
" --unit=UNIT Set default unit\n"
" --system Run a system instance, even if PID != 1\n"
" --user Run a user instance\n"
@@ -1130,20 +1132,14 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
if (r < 0)
return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m");
- *_f = f;
- *_fds = fds;
-
- f = NULL;
- fds = NULL;
+ *_f = TAKE_PTR(f);
+ *_fds = TAKE_PTR(fds);
return 0;
}
static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
- struct rlimit nl;
- int r;
- int min_max;
- _cleanup_free_ char *nr_open = NULL;
+ int r, nr;
assert(saved_rlimit);
@@ -1164,17 +1160,9 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
arg_default_rlimit[RLIMIT_NOFILE] = rl;
}
- /* Get current RLIMIT_NOFILE maximum compiled into the kernel. */
- r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
- if (r >= 0)
- r = safe_atoi(nr_open, &min_max);
- /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
- if (r < 0)
- min_max = 1024 * 1024;
-
- /* Bump up the resource limit for ourselves substantially */
- nl.rlim_cur = nl.rlim_max = min_max;
- r = setrlimit_closest(RLIMIT_NOFILE, &nl);
+ /* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows */
+ nr = read_nr_open();
+ r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(nr));
if (r < 0)
return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m");
@@ -1229,23 +1217,18 @@ static int enforce_syscall_archs(Set *archs) {
static int status_welcome(void) {
_cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
- const char *fn;
int r;
if (arg_show_status <= 0)
return 0;
- FOREACH_STRING(fn, "/etc/os-release", "/usr/lib/os-release") {
- r = parse_env_file(fn, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- "ANSI_COLOR", &ansi_color,
- NULL);
-
- if (r != -ENOENT)
- break;
- }
- if (r < 0 && r != -ENOENT)
- log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
+ r = parse_os_release(NULL,
+ "PRETTY_NAME", &pretty_name,
+ "ANSI_COLOR", &ansi_color,
+ NULL);
+ if (r < 0)
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to read os-release file, ignoring: %m");
if (log_get_show_color())
return status_printf(NULL, false, false,
@@ -1279,10 +1262,9 @@ static int bump_unix_max_dgram_qlen(void) {
unsigned long v;
int r;
- /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel
- * default of 16 is simply too low. We set the value really
- * really early during boot, so that it is actually applied to
- * all our sockets, including the $NOTIFY_SOCKET one. */
+ /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel default of 16 is simply too low. We set the value
+ * really really early during boot, so that it is actually applied to all our sockets, including the
+ * $NOTIFY_SOCKET one. */
r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen);
if (r < 0)
@@ -1290,16 +1272,12 @@ static int bump_unix_max_dgram_qlen(void) {
r = safe_atolu(qlen, &v);
if (r < 0)
- return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length, ignoring: %m");
+ return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length '%s', ignoring: %m", qlen);
if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN)
return 0;
- qlen = mfree(qlen);
- if (asprintf(&qlen, "%lu\n", DEFAULT_UNIX_MAX_DGRAM_QLEN) < 0)
- return log_oom();
-
- r = write_string_file("/proc/sys/net/unix/max_dgram_qlen", qlen, 0);
+ r = write_string_filef("/proc/sys/net/unix/max_dgram_qlen", 0, "%lu", DEFAULT_UNIX_MAX_DGRAM_QLEN);
if (r < 0)
return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to bump AF_UNIX datagram queue length, ignoring: %m");
@@ -1487,7 +1465,7 @@ static void initialize_clock(void) {
}
static void initialize_coredump(bool skip_setup) {
-
+#if ENABLE_COREDUMP
if (getpid_cached() != 1)
return;
@@ -1500,6 +1478,7 @@ static void initialize_coredump(bool skip_setup) {
* until the systemd-coredump tool is enabled via sysctl. */
if (!skip_setup)
disable_coredumps();
+#endif
}
static void do_reexecute(
@@ -1656,20 +1635,35 @@ static int invoke_main_loop(
switch (m->exit_code) {
- case MANAGER_RELOAD:
+ case MANAGER_RELOAD: {
+ LogTarget saved_log_target;
+ int saved_log_level;
+
log_info("Reloading.");
+ /* First, save any overridden log level/target, then parse the configuration file, which might
+ * change the log level to new settings. */
+
+ saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
+ saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID;
+
r = parse_config_file();
if (r < 0)
log_warning_errno(r, "Failed to parse config file, ignoring: %m");
set_manager_defaults(m);
+ if (saved_log_level >= 0)
+ manager_override_log_level(m, saved_log_level);
+ if (saved_log_target >= 0)
+ manager_override_log_target(m, saved_log_target);
+
r = manager_reload(m);
if (r < 0)
log_warning_errno(r, "Failed to reload, ignoring: %m");
break;
+ }
case MANAGER_REEXECUTE:
@@ -1865,6 +1859,13 @@ static int initialize_runtime(
}
}
+ if (arg_system && arg_no_new_privs) {
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+ *ret_error_message = "Failed to disable new privileges";
+ return log_emergency_errno(errno, "Failed to disable new privileges: %m");
+ }
+ }
+
if (arg_syscall_archs) {
r = enforce_syscall_archs(arg_syscall_archs);
if (r < 0) {
@@ -1898,28 +1899,15 @@ static int do_queue_default_job(
log_debug("Activating default unit: %s", arg_default_unit);
- r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
- if (r < 0)
- log_error("Failed to load default target: %s", bus_error_message(&error, r));
- else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND))
- log_error_errno(target->load_error, "Failed to load default target: %m");
- else if (target->load_state == UNIT_MASKED)
- log_error("Default target masked.");
-
- if (!target || target->load_state != UNIT_LOADED) {
- log_info("Trying to load rescue target...");
+ r = manager_load_startable_unit_or_warn(m, arg_default_unit, NULL, &target);
+ if (r < 0) {
+ log_info("Falling back to rescue target: " SPECIAL_RESCUE_TARGET);
- r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
+ r = manager_load_startable_unit_or_warn(m, SPECIAL_RESCUE_TARGET, NULL, &target);
if (r < 0) {
- *ret_error_message = "Failed to load rescue target";
- return log_emergency_errno(r, "Failed to load rescue target: %s", bus_error_message(&error, r));
- } else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND)) {
- *ret_error_message = "Failed to load rescue target";
- return log_emergency_errno(target->load_error, "Failed to load rescue target: %m");
- } else if (target->load_state == UNIT_MASKED) {
- *ret_error_message = "Rescue target masked";
- log_emergency("Rescue target masked.");
- return -ERFKILL;
+ *ret_error_message = r == -ERFKILL ? "Rescue target masked"
+ : "Failed to load rescue target";
+ return r;
}
}
@@ -1948,12 +1936,9 @@ static int do_queue_default_job(
}
static void free_arguments(void) {
- size_t j;
/* Frees all arg_* variables, with the exception of arg_serialization */
-
- for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++)
- arg_default_rlimit[j] = mfree(arg_default_rlimit[j]);
+ rlimit_free_all(arg_default_rlimit);
arg_default_unit = mfree(arg_default_unit);
arg_confirm_spawn = mfree(arg_confirm_spawn);
@@ -2150,7 +2135,6 @@ static bool early_skip_setup_check(int argc, char *argv[]) {
* anyway, even if in that case we also do deserialization. */
for (i = 1; i < argc; i++) {
-
if (streq(argv[i], "--switched-root"))
return false; /* If we switched root, don't skip the setup. */
else if (streq(argv[i], "--deserialize"))
@@ -2199,11 +2183,14 @@ int main(int argc, char *argv[]) {
log_set_upgrade_syslog_to_journal(true);
if (getpid_cached() == 1) {
+ /* When we run as PID 1 force system mode */
+ arg_system = true;
+
/* Disable the umask logic */
umask(0);
- /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be activated
- * yet (even though the log socket for it exists). */
+ /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be
+ * activated yet (even though the log socket for it exists). */
log_set_prohibit_ipc(true);
/* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is
@@ -2211,62 +2198,68 @@ int main(int argc, char *argv[]) {
* child process right before execve()'ing the actual binary, at a point in time where socket
* activation stderr/stdout area already set up. */
log_set_always_reopen_console(true);
- }
- if (getpid_cached() == 1 && detect_container() <= 0) {
+ if (detect_container() <= 0) {
- /* Running outside of a container as PID 1 */
- arg_system = true;
- log_set_target(LOG_TARGET_KMSG);
- log_open();
+ /* Running outside of a container as PID 1 */
+ log_set_target(LOG_TARGET_KMSG);
+ log_open();
- if (in_initrd())
- initrd_timestamp = userspace_timestamp;
+ if (in_initrd())
+ initrd_timestamp = userspace_timestamp;
- if (!skip_setup) {
- r = mount_setup_early();
- if (r < 0) {
- error_message = "Failed to mount early API filesystems";
- goto finish;
+ if (!skip_setup) {
+ r = mount_setup_early();
+ if (r < 0) {
+ error_message = "Failed to mount early API filesystems";
+ goto finish;
+ }
+
+ r = initialize_security(
+ &loaded_policy,
+ &security_start_timestamp,
+ &security_finish_timestamp,
+ &error_message);
+ if (r < 0)
+ goto finish;
}
- r = initialize_security(
- &loaded_policy,
- &security_start_timestamp,
- &security_finish_timestamp,
- &error_message);
- if (r < 0)
+ if (mac_selinux_init() < 0) {
+ error_message = "Failed to initialize SELinux policy";
goto finish;
- }
+ }
- if (mac_selinux_init() < 0) {
- error_message = "Failed to initialize SELinux policy";
- goto finish;
+ if (!skip_setup)
+ initialize_clock();
+
+ /* Set the default for later on, but don't actually open the logs like this for now. Note that
+ * if we are transitioning from the initrd there might still be journal fd open, and we
+ * shouldn't attempt opening that before we parsed /proc/cmdline which might redirect output
+ * elsewhere. */
+ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
+
+ } else {
+ /* Running inside a container, as PID 1 */
+ log_set_target(LOG_TARGET_CONSOLE);
+ log_open();
+
+ /* For later on, see above... */
+ log_set_target(LOG_TARGET_JOURNAL);
+
+ /* clear the kernel timestamp,
+ * because we are in a container */
+ kernel_timestamp = DUAL_TIMESTAMP_NULL;
}
- if (!skip_setup)
- initialize_clock();
-
- /* Set the default for later on, but don't actually
- * open the logs like this for now. Note that if we
- * are transitioning from the initrd there might still
- * be journal fd open, and we shouldn't attempt
- * opening that before we parsed /proc/cmdline which
- * might redirect output elsewhere. */
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
-
- } else if (getpid_cached() == 1) {
- /* Running inside a container, as PID 1 */
- arg_system = true;
- log_set_target(LOG_TARGET_CONSOLE);
- log_open();
+ initialize_coredump(skip_setup);
- /* For later on, see above... */
- log_set_target(LOG_TARGET_JOURNAL);
+ r = fixup_environment();
+ if (r < 0) {
+ log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
+ error_message = "Failed to fix up PID1 environment";
+ goto finish;
+ }
- /* clear the kernel timestamp,
- * because we are in a container */
- kernel_timestamp = DUAL_TIMESTAMP_NULL;
} else {
/* Running as user instance */
arg_system = false;
@@ -2278,24 +2271,14 @@ int main(int argc, char *argv[]) {
kernel_timestamp = DUAL_TIMESTAMP_NULL;
}
- initialize_coredump(skip_setup);
-
- r = fixup_environment();
- if (r < 0) {
- log_emergency_errno(r, "Failed to fix up PID 1 environment: %m");
- error_message = "Failed to fix up PID1 environment";
- goto finish;
- }
-
if (arg_system) {
-
- /* Try to figure out if we can use colors with the console. No
- * need to do that for user instances since they never log
- * into the console. */
+ /* Try to figure out if we can use colors with the console. No need to do that for user instances since
+ * they never log into the console. */
log_show_color(colors_enabled());
+
r = make_null_stdio();
if (r < 0)
- log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m");
+ log_warning_errno(r, "Failed to redirect standard streams to /dev/null, ignoring: %m");
}
/* Mount /proc, /sys and friends, so that /proc/cmdline and
@@ -2325,8 +2308,8 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS))
- pager_open(arg_no_pager, false);
+ if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES))
+ (void) pager_open(arg_no_pager, false);
if (arg_action != ACTION_RUN)
skip_setup = true;
@@ -2341,6 +2324,10 @@ int main(int argc, char *argv[]) {
unit_dump_config_items(stdout);
retval = EXIT_SUCCESS;
goto finish;
+ } else if (arg_action == ACTION_DUMP_BUS_PROPERTIES) {
+ dump_bus_properties(stdout);
+ retval = EXIT_SUCCESS;
+ goto finish;
}
assert_se(IN_SET(arg_action, ACTION_RUN, ACTION_TEST));
@@ -2439,10 +2426,10 @@ int main(int argc, char *argv[]) {
finish:
pager_close();
- if (m)
+ if (m) {
arg_shutdown_watchdog = m->shutdown_watchdog;
-
- m = manager_free(m);
+ m = manager_free(m);
+ }
free_arguments();
mac_selinux_finish();
@@ -2469,13 +2456,12 @@ finish:
* in become_shutdown() so normally we cannot free them yet. */
watchdog_free_device();
arg_watchdog_device = mfree(arg_watchdog_device);
- return 0;
+ return retval;
}
#endif
if (shutdown_verb) {
r = become_shutdown(shutdown_verb, retval);
-
log_error_errno(r, "Failed to execute shutdown binary, %s: %m", getpid_cached() == 1 ? "freezing" : "quitting");
error_message = "Failed to execute shutdown binary";
}
diff --git a/src/core/manager.c b/src/core/manager.c
index 84adb9c666..930df4e23a 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -41,6 +23,7 @@
#include "sd-path.h"
#include "alloc-util.h"
+#include "all-units.h"
#include "audit-fd.h"
#include "boot-timestamps.h"
#include "bus-common-errors.h"
@@ -76,14 +59,17 @@
#include "path-util.h"
#include "process-util.h"
#include "ratelimit.h"
+#include "rlimit-util.h"
#include "rm-rf.h"
#include "signal-util.h"
+#include "socket-util.h"
#include "special.h"
#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "strxcpyx.h"
+#include "syslog-util.h"
#include "terminal-util.h"
#include "time-util.h"
#include "transaction.h"
@@ -118,6 +104,7 @@ static int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint
static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
static int manager_dispatch_run_queue(sd_event_source *source, void *userdata);
static int manager_dispatch_sigchld(sd_event_source *source, void *userdata);
+static int manager_dispatch_timezone_change(sd_event_source *source, const struct inotify_event *event, void *userdata);
static int manager_run_environment_generators(Manager *m);
static int manager_run_generators(Manager *m);
@@ -362,35 +349,27 @@ static void manager_close_idle_pipe(Manager *m) {
static int manager_setup_time_change(Manager *m) {
int r;
- /* We only care for the cancellation event, hence we set the
- * timeout to the latest possible value. */
- struct itimerspec its = {
- .it_value.tv_sec = TIME_T_MAX,
- };
-
assert(m);
- assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
if (m->test_run_flags)
return 0;
- /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
- * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
+ m->time_change_event_source = sd_event_source_unref(m->time_change_event_source);
+ m->time_change_fd = safe_close(m->time_change_fd);
- m->time_change_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+ m->time_change_fd = time_change_fd();
if (m->time_change_fd < 0)
- return log_error_errno(errno, "Failed to create timerfd: %m");
-
- if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
- log_debug_errno(errno, "Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
- m->time_change_fd = safe_close(m->time_change_fd);
- return 0;
- }
+ return log_error_errno(m->time_change_fd, "Failed to create timer change timer fd: %m");
r = sd_event_add_io(m->event, &m->time_change_event_source, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m);
if (r < 0)
return log_error_errno(r, "Failed to create time change event source: %m");
+ /* Schedule this slightly earlier than the .timer event sources */
+ r = sd_event_source_set_priority(m->time_change_event_source, SD_EVENT_PRIORITY_NORMAL-1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set priority of time change event sources: %m");
+
(void) sd_event_source_set_description(m->time_change_event_source, "manager-time-change");
log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
@@ -398,6 +377,70 @@ static int manager_setup_time_change(Manager *m) {
return 0;
}
+static int manager_read_timezone_stat(Manager *m) {
+ struct stat st;
+ bool changed;
+
+ assert(m);
+
+ /* Read the current stat() data of /etc/localtime so that we detect changes */
+ if (lstat("/etc/localtime", &st) < 0) {
+ log_debug_errno(errno, "Failed to stat /etc/localtime, ignoring: %m");
+ changed = m->etc_localtime_accessible;
+ m->etc_localtime_accessible = false;
+ } else {
+ usec_t k;
+
+ k = timespec_load(&st.st_mtim);
+ changed = !m->etc_localtime_accessible || k != m->etc_localtime_mtime;
+
+ m->etc_localtime_mtime = k;
+ m->etc_localtime_accessible = true;
+ }
+
+ return changed;
+}
+
+static int manager_setup_timezone_change(Manager *m) {
+ _cleanup_(sd_event_source_unrefp) sd_event_source *new_event = NULL;
+ int r;
+
+ assert(m);
+
+ if (m->test_run_flags != 0)
+ return 0;
+
+ /* We watch /etc/localtime for three events: change of the link count (which might mean removal from /etc even
+ * though another link might be kept), renames, and file close operations after writing. Note we don't bother
+ * with IN_DELETE_SELF, as that would just report when the inode is removed entirely, i.e. after the link count
+ * went to zero and all fds to it are closed.
+ *
+ * Note that we never follow symlinks here. This is a simplification, but should cover almost all cases
+ * correctly.
+ *
+ * Note that we create the new event source first here, before releasing the old one. This should optimize
+ * behaviour as this way sd-event can reuse the old watch in case the inode didn't change. */
+
+ r = sd_event_add_inotify(m->event, &new_event, "/etc/localtime",
+ IN_ATTRIB|IN_MOVE_SELF|IN_CLOSE_WRITE|IN_DONT_FOLLOW, manager_dispatch_timezone_change, m);
+ if (r == -ENOENT) /* If the file doesn't exist yet, subscribe to /etc instead, and wait until it is created
+ * either by O_CREATE or by rename() */
+ r = sd_event_add_inotify(m->event, &new_event, "/etc",
+ IN_CREATE|IN_MOVED_TO|IN_ONLYDIR, manager_dispatch_timezone_change, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create timezone change event source: %m");
+
+ /* Schedule this slightly earlier than the .timer event sources */
+ r = sd_event_source_set_priority(new_event, SD_EVENT_PRIORITY_NORMAL-1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set priority of timezone change event sources: %m");
+
+ sd_event_source_unref(m->timezone_change_event_source);
+ m->timezone_change_event_source = TAKE_PTR(new_event);
+
+ return 0;
+}
+
static int enable_special_signals(Manager *m) {
_cleanup_close_ int fd = -1;
@@ -426,6 +469,8 @@ static int enable_special_signals(Manager *m) {
return 0;
}
+#define RTSIG_IF_AVAILABLE(signum) (signum <= SIGRTMAX ? signum : -1)
+
static int manager_setup_signals(Manager *m) {
struct sigaction sa = {
.sa_handler = SIG_DFL,
@@ -479,22 +524,22 @@ static int manager_setup_signals(Manager *m) {
/* .. one free signal here ... */
-#if !defined(__hppa64__) && !defined(__hppa__)
- /* Apparently Linux on hppa has fewer RT
- * signals (SIGRTMAX is SIGRTMIN+25 there),
- * hence let's not try to make use of them
- * here. Since these commands are accessible
- * by different means and only really a safety
- * net, the missing functionality on hppa
- * shouldn't matter. */
-
- SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
- SIGRTMIN+27, /* systemd: set log target to console */
- SIGRTMIN+28, /* systemd: set log target to kmsg */
- SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg (obsolete) */
+ /* Apparently Linux on hppa had fewer RT signals until v3.18,
+ * SIGRTMAX was SIGRTMIN+25, and then SIGRTMIN was lowered,
+ * see commit v3.17-7614-g1f25df2eff.
+ *
+ * We cannot unconditionally make use of those signals here,
+ * so let's use a runtime check. Since these commands are
+ * accessible by different means and only really a safety
+ * net, the missing functionality on hppa shouldn't matter.
+ */
+
+ RTSIG_IF_AVAILABLE(SIGRTMIN+26), /* systemd: set log target to journal-or-kmsg */
+ RTSIG_IF_AVAILABLE(SIGRTMIN+27), /* systemd: set log target to console */
+ RTSIG_IF_AVAILABLE(SIGRTMIN+28), /* systemd: set log target to kmsg */
+ RTSIG_IF_AVAILABLE(SIGRTMIN+29), /* systemd: set log target to syslog-or-kmsg (obsolete) */
/* ... one free signal here SIGRTMIN+30 ... */
-#endif
-1);
assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
@@ -667,7 +712,7 @@ static int manager_setup_sigchld_event_source(Manager *m) {
}
int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) {
- Manager *m;
+ _cleanup_(manager_freep) Manager *m = NULL;
int r;
assert(_m);
@@ -686,6 +731,8 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) {
m->default_timeout_start_usec = DEFAULT_TIMEOUT_USEC;
m->default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
m->default_restart_usec = DEFAULT_RESTART_USEC;
+ m->original_log_level = -1;
+ m->original_log_target = _LOG_TARGET_INVALID;
#if ENABLE_EFI
if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0)
@@ -729,62 +776,74 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) {
r = manager_default_environment(m);
if (r < 0)
- goto fail;
+ return r;
r = hashmap_ensure_allocated(&m->units, &string_hash_ops);
if (r < 0)
- goto fail;
+ return r;
r = hashmap_ensure_allocated(&m->jobs, NULL);
if (r < 0)
- goto fail;
+ return r;
r = hashmap_ensure_allocated(&m->cgroup_unit, &path_hash_ops);
if (r < 0)
- goto fail;
+ return r;
r = hashmap_ensure_allocated(&m->watch_bus, &string_hash_ops);
if (r < 0)
- goto fail;
+ return r;
+
+ r = manager_setup_prefix(m);
+ if (r < 0)
+ return r;
+
+ m->udev = udev_new();
+ if (!m->udev)
+ return -ENOMEM;
r = sd_event_default(&m->event);
if (r < 0)
- goto fail;
+ return r;
r = manager_setup_run_queue(m);
if (r < 0)
- goto fail;
+ return r;
- r = manager_setup_signals(m);
- if (r < 0)
- goto fail;
+ if (test_run_flags == MANAGER_TEST_RUN_MINIMAL) {
+ m->cgroup_root = strdup("");
+ if (!m->cgroup_root)
+ return -ENOMEM;
+ } else {
+ r = manager_setup_signals(m);
+ if (r < 0)
+ return r;
- r = manager_setup_cgroup(m);
- if (r < 0)
- goto fail;
+ r = manager_setup_cgroup(m);
+ if (r < 0)
+ return r;
- r = manager_setup_time_change(m);
- if (r < 0)
- goto fail;
+ r = manager_setup_time_change(m);
+ if (r < 0)
+ return r;
- r = manager_setup_sigchld_event_source(m);
- if (r < 0)
- goto fail;
+ r = manager_read_timezone_stat(m);
+ if (r < 0)
+ return r;
- m->udev = udev_new();
- if (!m->udev) {
- r = -ENOMEM;
- goto fail;
- }
+ r = manager_setup_timezone_change(m);
+ if (r < 0)
+ return r;
- r = manager_setup_prefix(m);
- if (r < 0)
- goto fail;
+ r = manager_setup_sigchld_event_source(m);
+ if (r < 0)
+ return r;
+ }
if (MANAGER_IS_SYSTEM(m) && test_run_flags == 0) {
r = mkdir_label("/run/systemd/units", 0755);
if (r < 0 && r != -EEXIST)
- goto fail;
+ return r;
}
m->taint_usr =
@@ -794,12 +853,9 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) {
/* Note that we do not set up the notify fd here. We do that after deserialization,
* since they might have gotten serialized across the reexec. */
- *_m = m;
- return 0;
+ *_m = TAKE_PTR(m);
-fail:
- manager_free(m);
- return r;
+ return 0;
}
static int manager_setup_notify(Manager *m) {
@@ -841,8 +897,7 @@ static int manager_setup_notify(Manager *m) {
if (r < 0)
return log_error_errno(errno, "SO_PASSCRED failed: %m");
- m->notify_fd = fd;
- fd = -1;
+ m->notify_fd = TAKE_FD(fd);
log_debug("Using notification socket %s", m->notify_socket);
}
@@ -1183,7 +1238,6 @@ static void manager_clear_jobs_and_units(Manager *m) {
Manager* manager_free(Manager *m) {
UnitType c;
- int i;
ExecDirectoryType dt;
if (!m)
@@ -1222,6 +1276,7 @@ Manager* manager_free(Manager *m) {
sd_event_source_unref(m->notify_event_source);
sd_event_source_unref(m->cgroups_agent_event_source);
sd_event_source_unref(m->time_change_event_source);
+ sd_event_source_unref(m->timezone_change_event_source);
sd_event_source_unref(m->jobs_in_progress_event_source);
sd_event_source_unref(m->run_queue_event_source);
sd_event_source_unref(m->user_lookup_event_source);
@@ -1251,8 +1306,7 @@ Manager* manager_free(Manager *m) {
free(m->switch_root);
free(m->switch_root_init);
- for (i = 0; i < _RLIMIT_MAX; i++)
- m->rlimit[i] = mfree(m->rlimit[i]);
+ rlimit_free_all(m->rlimit);
assert(hashmap_isempty(m->units_requiring_mounts_for));
hashmap_free(m->units_requiring_mounts_for);
@@ -1266,23 +1320,37 @@ Manager* manager_free(Manager *m) {
return mfree(m);
}
-void manager_enumerate(Manager *m) {
+static void manager_enumerate_perpetual(Manager *m) {
UnitType c;
assert(m);
- /* Let's ask every type to load all units from disk/kernel
- * that it might know */
+ /* 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_type_supported(c)) {
log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
continue;
}
- if (!unit_vtable[c]->enumerate)
+ if (unit_vtable[c]->enumerate_perpetual)
+ unit_vtable[c]->enumerate_perpetual(m);
+ }
+}
+
+static void manager_enumerate(Manager *m) {
+ UnitType c;
+
+ assert(m);
+
+ /* Let's ask every type to load all units from disk/kernel that it might know */
+ for (c = 0; c < _UNIT_TYPE_MAX; c++) {
+ if (!unit_type_supported(c)) {
+ log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
continue;
+ }
- unit_vtable[c]->enumerate(m);
+ if (unit_vtable[c]->enumerate)
+ unit_vtable[c]->enumerate(m);
}
manager_dispatch_load_queue(m);
@@ -1296,7 +1364,9 @@ static void manager_coldplug(Manager *m) {
assert(m);
- /* Then, let's set up their initial state. */
+ log_debug("Invoking unit coldplug() handlers…");
+
+ /* Let's place the units back into their deserialized state */
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
/* ignore aliases */
@@ -1309,6 +1379,26 @@ static void manager_coldplug(Manager *m) {
}
}
+static void manager_catchup(Manager *m) {
+ Iterator i;
+ Unit *u;
+ char *k;
+
+ assert(m);
+
+ log_debug("Invoking unit catchup() handlers…");
+
+ /* Let's catch up on any state changes that happened while we were reloading/reexecing */
+ HASHMAP_FOREACH_KEY(u, k, m->units, i) {
+
+ /* ignore aliases */
+ if (u->id != k)
+ continue;
+
+ unit_catchup(u);
+ }
+}
+
static void manager_build_unit_path_cache(Manager *m) {
char **i;
int r;
@@ -1409,6 +1499,48 @@ static bool manager_dbus_is_running(Manager *m, bool deserialized) {
return true;
}
+static void manager_setup_bus(Manager *m) {
+ assert(m);
+
+ /* Let's set up our private bus connection now, unconditionally */
+ (void) bus_init_private(m);
+
+ /* If we are in --user mode also connect to the system bus now */
+ if (MANAGER_IS_USER(m))
+ (void) bus_init_system(m);
+
+ /* Let's connect to the bus now, but only if the unit is supposed to be up */
+ if (manager_dbus_is_running(m, MANAGER_IS_RELOADING(m))) {
+ (void) bus_init_api(m);
+
+ if (MANAGER_IS_SYSTEM(m))
+ (void) bus_init_system(m);
+ }
+}
+
+static void manager_preset_all(Manager *m) {
+ int r;
+
+ assert(m);
+
+ if (m->first_boot <= 0)
+ return;
+
+ if (!MANAGER_IS_SYSTEM(m))
+ return;
+
+ if (m->test_run_flags != 0)
+ return;
+
+ /* If this is the first boot, and we are in the host system, then preset everything */
+ r = unit_file_preset_all(UNIT_FILE_SYSTEM, 0, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, NULL, 0);
+ if (r < 0)
+ log_full_errno(r == -EEXIST ? LOG_NOTICE : LOG_WARNING, r,
+ "Failed to populate /etc with preset unit settings, ignoring: %m");
+ else
+ log_info("Populated /etc with preset unit settings.");
+}
+
int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
int r;
@@ -1432,19 +1564,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
if (r < 0)
return r;
- /* If this is the first boot, and we are in the host system, then preset everything */
- if (m->first_boot > 0 &&
- MANAGER_IS_SYSTEM(m) &&
- !m->test_run_flags) {
-
- r = unit_file_preset_all(UNIT_FILE_SYSTEM, 0, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, NULL, 0);
- if (r < 0)
- log_full_errno(r == -EEXIST ? LOG_NOTICE : LOG_WARNING, r,
- "Failed to populate /etc with preset unit settings, ignoring: %m");
- else
- log_info("Populated /etc with preset unit settings.");
- }
-
+ manager_preset_all(m);
lookup_paths_reduce(&m->lookup_paths);
manager_build_unit_path_cache(m);
@@ -1456,6 +1576,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
/* First, enumerate what we can from all config files */
dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_UNITS_LOAD_START);
+ manager_enumerate_perpetual(m);
manager_enumerate(m);
dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_UNITS_LOAD_FINISH);
@@ -1489,20 +1610,8 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
/* This shouldn't fail, except if things are really broken. */
return r;
- /* Let's set up our private bus connection now, unconditionally */
- (void) bus_init_private(m);
-
- /* If we are in --user mode also connect to the system bus now */
- if (MANAGER_IS_USER(m))
- (void) bus_init_system(m);
-
- /* Let's connect to the bus now, but only if the unit is supposed to be up */
- if (manager_dbus_is_running(m, !!serialization)) {
- (void) bus_init_api(m);
-
- if (MANAGER_IS_SYSTEM(m))
- (void) bus_init_system(m);
- }
+ /* Connect to the bus if we are good for it */
+ manager_setup_bus(m);
/* Now that we are connected to all possible busses, let's deserialize who is tracking us. */
(void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed);
@@ -1530,6 +1639,9 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
m->send_reloading_done = true;
}
+ /* Let's finally catch up with any changes that took place while we were reloading/reexecing */
+ manager_catchup(m);
+
return 0;
}
@@ -1668,6 +1780,42 @@ Unit *manager_get_unit(Manager *m, const char *name) {
return hashmap_get(m->units, name);
}
+static int manager_dispatch_target_deps_queue(Manager *m) {
+ Unit *u;
+ unsigned k;
+ int r = 0;
+
+ static const UnitDependency deps[] = {
+ UNIT_REQUIRED_BY,
+ UNIT_REQUISITE_OF,
+ UNIT_WANTED_BY,
+ UNIT_BOUND_BY
+ };
+
+ assert(m);
+
+ while ((u = m->target_deps_queue)) {
+ assert(u->in_target_deps_queue);
+
+ LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u);
+ u->in_target_deps_queue = false;
+
+ for (k = 0; k < ELEMENTSOF(deps); k++) {
+ Unit *target;
+ Iterator i;
+ void *v;
+
+ HASHMAP_FOREACH_KEY(v, target, u->dependencies[deps[k]], i) {
+ r = unit_add_default_target_dependency(u, target);
+ if (r < 0)
+ return r;
+ }
+ }
+ }
+
+ return r;
+}
+
unsigned manager_dispatch_load_queue(Manager *m) {
Unit *u;
unsigned n = 0;
@@ -1691,6 +1839,11 @@ unsigned manager_dispatch_load_queue(Manager *m) {
}
m->dispatching_load_queue = false;
+
+ /* Dispatch the units waiting for their target dependencies to be added now, as all targets that we know about
+ * should be loaded and have aliases resolved */
+ (void) manager_dispatch_target_deps_queue(m);
+
return n;
}
@@ -1701,6 +1854,7 @@ int manager_load_unit_prepare(
sd_bus_error *e,
Unit **_ret) {
+ _cleanup_(unit_freep) Unit *cleanup_ret = NULL;
Unit *ret;
UnitType t;
int r;
@@ -1733,29 +1887,26 @@ int manager_load_unit_prepare(
return 1;
}
- ret = unit_new(m, unit_vtable[t]->object_size);
+ ret = cleanup_ret = unit_new(m, unit_vtable[t]->object_size);
if (!ret)
return -ENOMEM;
if (path) {
ret->fragment_path = strdup(path);
- if (!ret->fragment_path) {
- unit_free(ret);
+ if (!ret->fragment_path)
return -ENOMEM;
- }
}
r = unit_add_name(ret, name);
- if (r < 0) {
- unit_free(ret);
+ if (r < 0)
return r;
- }
unit_add_to_load_queue(ret);
unit_add_to_dbus_queue(ret);
unit_add_to_gc_queue(ret);
*_ret = ret;
+ cleanup_ret = NULL;
return 0;
}
@@ -1782,7 +1933,32 @@ int manager_load_unit(
manager_dispatch_load_queue(m);
*_ret = unit_follow_merge(*_ret);
+ return 0;
+}
+
+int manager_load_startable_unit_or_warn(
+ Manager *m,
+ const char *name,
+ const char *path,
+ Unit **ret) {
+
+ /* Load a unit, make sure it loaded fully and is not masked. */
+
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ Unit *unit;
+ int r;
+ r = manager_load_unit(m, name, path, &error, &unit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to load %s %s: %s",
+ name ? "unit" : "unit file", name ?: path,
+ bus_error_message(&error, r));
+
+ r = bus_unit_validate_load_state(unit, &error);
+ if (r < 0)
+ return log_error_errno(r, "%s", bus_error_message(&error, r));
+
+ *ret = unit;
return 0;
}
@@ -1853,8 +2029,7 @@ int manager_get_dump_string(Manager *m, char **ret) {
f = safe_fclose(f);
- *ret = dump;
- dump = NULL;
+ *ret = TAKE_PTR(dump);
return 0;
}
@@ -2049,7 +2224,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
_cleanup_free_ Unit **array_copy = NULL;
Unit *u1, *u2, **array;
int r, *fd_array = NULL;
- unsigned n_fds = 0;
+ size_t n_fds = 0;
bool found = false;
ssize_t n;
@@ -2283,7 +2458,7 @@ static void manager_handle_ctrl_alt_del(Manager *m) {
* 7 times within 2s, we reboot/shutdown immediately,
* unless it was disabled in system.conf */
- if (ratelimit_test(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE)
+ if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE)
manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
else
emergency_action(m, m->cad_burst_action, NULL,
@@ -2335,8 +2510,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
case SIGTERM:
if (MANAGER_IS_SYSTEM(m)) {
- /* This is for compatibility with the
- * original sysvinit */
+ /* This is for compatibility with the original sysvinit */
r = verify_run_space_and_log("Refusing to reexecute");
if (r >= 0)
m->exit_code = MANAGER_REEXECUTE;
@@ -2353,21 +2527,20 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
break;
case SIGWINCH:
+ /* This is a nop on non-init */
if (MANAGER_IS_SYSTEM(m))
manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
- /* This is a nop on non-init */
break;
case SIGPWR:
+ /* This is a nop on non-init */
if (MANAGER_IS_SYSTEM(m))
manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
- /* This is a nop on non-init */
break;
case SIGUSR1:
-
if (manager_dbus_is_running(m, false)) {
log_info("Trying to reconnect to bus...");
@@ -2450,13 +2623,11 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
break;
case 22:
- log_set_max_level(LOG_DEBUG);
- log_info("Setting log level to debug.");
+ manager_override_log_level(m, LOG_DEBUG);
break;
case 23:
- log_set_max_level(LOG_INFO);
- log_info("Setting log level to info.");
+ manager_restore_original_log_level(m);
break;
case 24:
@@ -2470,18 +2641,15 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
case 26:
case 29: /* compatibility: used to be mapped to LOG_TARGET_SYSLOG_OR_KMSG */
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
- log_notice("Setting log target to journal-or-kmsg.");
+ manager_restore_original_log_target(m);
break;
case 27:
- log_set_target(LOG_TARGET_CONSOLE);
- log_notice("Setting log target to console.");
+ manager_override_log_target(m, LOG_TARGET_CONSOLE);
break;
case 28:
- log_set_target(LOG_TARGET_KMSG);
- log_notice("Setting log target to kmsg.");
+ manager_override_log_target(m, LOG_TARGET_KMSG);
break;
default:
@@ -2502,14 +2670,10 @@ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint
log_struct(LOG_DEBUG,
"MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR,
- LOG_MESSAGE("Time has been changed"),
- NULL);
+ LOG_MESSAGE("Time has been changed"));
/* Restart the watch */
- m->time_change_event_source = sd_event_source_unref(m->time_change_event_source);
- m->time_change_fd = safe_close(m->time_change_fd);
-
- manager_setup_time_change(m);
+ (void) manager_setup_time_change(m);
HASHMAP_FOREACH(u, m->units, i)
if (UNIT_VTABLE(u)->time_change)
@@ -2518,6 +2682,41 @@ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint
return 0;
}
+static int manager_dispatch_timezone_change(
+ sd_event_source *source,
+ const struct inotify_event *e,
+ void *userdata) {
+
+ Manager *m = userdata;
+ int changed;
+ Iterator i;
+ Unit *u;
+
+ assert(m);
+
+ log_debug("inotify event for /etc/localtime");
+
+ changed = manager_read_timezone_stat(m);
+ if (changed < 0)
+ return changed;
+ if (!changed)
+ return 0;
+
+ /* Something changed, restart the watch, to ensure we watch the new /etc/localtime if it changed */
+ (void) manager_setup_timezone_change(m);
+
+ /* Read the new timezone */
+ tzset();
+
+ log_debug("Timezone has been changed (now: %s).", tzname[daylight]);
+
+ HASHMAP_FOREACH(u, m->units, i)
+ if (UNIT_VTABLE(u)->timezone_change)
+ UNIT_VTABLE(u)->timezone_change(u);
+
+ return 0;
+}
+
static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
@@ -2580,7 +2779,7 @@ int manager_loop(Manager *m) {
if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m))
watchdog_ping();
- if (!ratelimit_test(&rl)) {
+ if (!ratelimit_below(&rl)) {
/* Yay, something is going seriously wrong, pause a little */
log_warning("Looping too fast. Throttling execution a little.");
sleep(1);
@@ -2644,12 +2843,19 @@ int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e,
return 0;
}
- return sd_bus_error_setf(e, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(invocation_id));
+ return sd_bus_error_setf(e, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID,
+ "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.",
+ SD_ID128_FORMAT_VAL(invocation_id));
}
/* If this didn't work, we check if this is a unit name */
- if (!unit_name_is_valid(n, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
- return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is neither a valid invocation ID nor unit name.", n);
+ if (!unit_name_is_valid(n, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
+ _cleanup_free_ char *nn = NULL;
+
+ nn = cescape(n);
+ return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS,
+ "Unit name %s is neither a valid invocation ID nor unit name.", strnull(nn));
+ }
r = manager_load_unit(m, n, NULL, e, &u);
if (r < 0)
@@ -2813,6 +3019,11 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
fprintf(f, "taint-logged=%s\n", yes_no(m->taint_logged));
fprintf(f, "service-watchdogs=%s\n", yes_no(m->service_watchdogs));
+ if (m->log_level_overridden)
+ fprintf(f, "log-level-override=%i\n", log_get_max_level());
+ if (m->log_target_overridden)
+ fprintf(f, "log-target-override=%s\n", log_target_to_string(log_get_target()));
+
for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
/* The userspace and finish timestamps only apply to the host system, hence only serialize them there */
if (in_initrd() && IN_SET(q, MANAGER_TIMESTAMP_USERSPACE, MANAGER_TIMESTAMP_FINISH))
@@ -2897,8 +3108,9 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
assert(m->n_reloading > 0);
m->n_reloading--;
- if (ferror(f))
- return -EIO;
+ r = fflush_and_check(f);
+ if (r < 0)
+ return r;
r = bus_fdset_add_all(m, fds);
if (r < 0)
@@ -2996,6 +3208,24 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
else
m->service_watchdogs = b;
+ } else if ((val = startswith(l, "log-level-override="))) {
+ int level;
+
+ level = log_level_from_string(val);
+ if (level < 0)
+ log_notice("Failed to parse log-level-override value '%s', ignoring.", val);
+ else
+ manager_override_log_level(m, level);
+
+ } else if ((val = startswith(l, "log-target-override="))) {
+ LogTarget target;
+
+ target = log_target_from_string(val);
+ if (target < 0)
+ log_notice("Failed to parse log-target-override value '%s', ignoring.", val);
+ else
+ manager_override_log_target(m, target);
+
} else if (startswith(l, "env=")) {
r = deserialize_environment(&m->environment, l);
if (r == -ENOMEM)
@@ -3126,6 +3356,17 @@ finish:
return r;
}
+static void manager_flush_finished_jobs(Manager *m) {
+ Job *j;
+
+ while ((j = set_steal_first(m->pending_finished_jobs))) {
+ bus_job_send_removed_signal(j);
+ job_free(j);
+ }
+
+ m->pending_finished_jobs = set_free(m->pending_finished_jobs);
+}
+
int manager_reload(Manager *m) {
int r, q;
_cleanup_fclose_ FILE *f = NULL;
@@ -3194,8 +3435,7 @@ int manager_reload(Manager *m) {
r = q;
}
- fclose(f);
- f = NULL;
+ f = safe_fclose(f);
/* Re-register notify_fd as event source */
q = manager_setup_notify(m);
@@ -3222,17 +3462,23 @@ int manager_reload(Manager *m) {
exec_runtime_vacuum(m);
+ assert(m->n_reloading > 0);
+ m->n_reloading--;
+
/* It might be safe to log to the journal now and connect to dbus */
manager_recheck_journal(m);
manager_recheck_dbus(m);
+ /* Let's finally catch up with any changes that took place while we were reloading/reexecing */
+ manager_catchup(m);
+
/* Sync current state of bus names with our set of listening units */
q = manager_enqueue_sync_bus_names(m);
if (q < 0 && r >= 0)
r = q;
- assert(m->n_reloading > 0);
- m->n_reloading--;
+ if (!MANAGER_IS_RELOADING(m))
+ manager_flush_finished_jobs(m);
m->send_reloading_done = true;
@@ -3280,8 +3526,7 @@ static void log_taint_string(Manager *m) {
log_struct(LOG_NOTICE,
LOG_MESSAGE("System is tainted: %s", taint),
"TAINT=%s", taint,
- "MESSAGE_ID=" SD_MESSAGE_TAINTED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_TAINTED_STR);
}
static void manager_notify_finished(Manager *m) {
@@ -3328,8 +3573,7 @@ static void manager_notify_finished(Manager *m) {
format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
format_timespan(initrd, sizeof(initrd), initrd_usec, USEC_PER_MSEC),
format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
- format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)),
- NULL);
+ format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)));
} else {
/* The initrd-less case on bare-metal*/
@@ -3344,8 +3588,7 @@ static void manager_notify_finished(Manager *m) {
buf,
format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
- format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)),
- NULL);
+ format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)));
}
} else {
/* The container and --user case */
@@ -3356,8 +3599,7 @@ static void manager_notify_finished(Manager *m) {
"MESSAGE_ID=" SD_MESSAGE_USER_STARTUP_FINISHED_STR,
"USERSPACE_USEC="USEC_FMT, userspace_usec,
LOG_MESSAGE("Startup finished in %s.",
- format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)),
- NULL);
+ format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)));
}
bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
@@ -3597,6 +3839,9 @@ void manager_recheck_dbus(Manager *m) {
* connection of the API bus). That's because the system bus after all runs as service of the system instance,
* while in the user instance we can assume it's already there. */
+ if (MANAGER_IS_RELOADING(m))
+ return; /* don't check while we are reloading… */
+
if (manager_dbus_is_running(m, false)) {
(void) bus_init_api(m);
@@ -3647,6 +3892,10 @@ void manager_recheck_journal(Manager *m) {
if (getpid_cached() != 1)
return;
+ /* Don't check this while we are reloading, things might still change */
+ if (MANAGER_IS_RELOADING(m))
+ return;
+
/* The journal is fully and entirely up? If so, let's permit logging to it, if that's configured. If the
* journal is down, don't ever log to it, otherwise we might end up deadlocking ourselves as we might trigger
* an activation ourselves we can't fulfill. */
@@ -3786,7 +4035,7 @@ Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
assert(path);
strcpy(p, path);
- path_kill_slashes(p);
+ path_simplify(p, false);
return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
}
@@ -4215,6 +4464,59 @@ void manager_unref_console(Manager *m) {
m->no_console_output = false; /* unset no_console_output flag, since the console is definitely free now */
}
+void manager_override_log_level(Manager *m, int level) {
+ _cleanup_free_ char *s = NULL;
+ assert(m);
+
+ if (!m->log_level_overridden) {
+ m->original_log_level = log_get_max_level();
+ m->log_level_overridden = true;
+ }
+
+ (void) log_level_to_string_alloc(level, &s);
+ log_info("Setting log level to %s.", strna(s));
+
+ log_set_max_level(level);
+}
+
+void manager_restore_original_log_level(Manager *m) {
+ _cleanup_free_ char *s = NULL;
+ assert(m);
+
+ if (!m->log_level_overridden)
+ return;
+
+ (void) log_level_to_string_alloc(m->original_log_level, &s);
+ log_info("Restoring log level to original (%s).", strna(s));
+
+ log_set_max_level(m->original_log_level);
+ m->log_level_overridden = false;
+}
+
+void manager_override_log_target(Manager *m, LogTarget target) {
+ assert(m);
+
+ if (!m->log_target_overridden) {
+ m->original_log_target = log_get_target();
+ m->log_target_overridden = true;
+ }
+
+ log_info("Setting log target to %s.", log_target_to_string(target));
+ log_set_target(target);
+}
+
+void manager_restore_original_log_target(Manager *m) {
+ assert(m);
+
+ if (!m->log_target_overridden)
+ return;
+
+ log_info("Restoring log target to original %s.", log_target_to_string(m->original_log_target));
+
+ log_set_target(m->original_log_target);
+ m->log_target_overridden = false;
+}
+
static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
[MANAGER_INITIALIZING] = "initializing",
[MANAGER_STARTING] = "starting",
diff --git a/src/core/manager.h b/src/core/manager.h
index 152640bd83..ea5d425030 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdio.h>
@@ -34,6 +15,7 @@
#include "ratelimit.h"
struct libmnt_monitor;
+typedef struct Unit Unit;
/* Enforce upper limit how many names we allow */
#define MANAGER_MAX_NAMES 131072 /* 128K */
@@ -97,10 +79,11 @@ typedef enum ManagerTimestamp {
enum {
/* 0 = run normally */
- MANAGER_TEST_RUN_MINIMAL = 1, /* run test w/o generators */
- MANAGER_TEST_RUN_ENV_GENERATORS = 2, /* also run env generators */
- MANAGER_TEST_RUN_GENERATORS = 4, /* also run unit generators */
- MANAGER_TEST_FULL = MANAGER_TEST_RUN_ENV_GENERATORS | MANAGER_TEST_RUN_GENERATORS,
+ MANAGER_TEST_RUN_MINIMAL = 1 << 1, /* create basic data structures */
+ MANAGER_TEST_RUN_BASIC = 1 << 2, /* interact with the environment */
+ MANAGER_TEST_RUN_ENV_GENERATORS = 1 << 3, /* also run env generators */
+ MANAGER_TEST_RUN_GENERATORS = 1 << 4, /* also run unit generators */
+ MANAGER_TEST_FULL = MANAGER_TEST_RUN_BASIC | MANAGER_TEST_RUN_ENV_GENERATORS | MANAGER_TEST_RUN_GENERATORS,
};
assert_cc((MANAGER_TEST_FULL & UINT8_MAX) == MANAGER_TEST_FULL);
@@ -144,6 +127,9 @@ struct Manager {
/* Units whose cgroup ran empty */
LIST_HEAD(Unit, cgroup_empty_queue);
+ /* Target units whose default target dependencies haven't been set yet */
+ LIST_HEAD(Unit, target_deps_queue);
+
sd_event *event;
/* This maps PIDs we care about to units that are interested in. We allow multiple units to he interested in
@@ -178,6 +164,8 @@ struct Manager {
int time_change_fd;
sd_event_source *time_change_event_source;
+ sd_event_source *timezone_change_event_source;
+
sd_event_source *jobs_in_progress_event_source;
int user_lookup_fds[2];
@@ -258,6 +246,10 @@ struct Manager {
unsigned gc_marker;
+ /* The stat() data the last time we saw /etc/localtime */
+ usec_t etc_localtime_mtime;
+ bool etc_localtime_accessible:1;
+
/* Flags */
ManagerExitCode exit_code:5;
@@ -304,10 +296,18 @@ struct Manager {
uint64_t default_tasks_max;
usec_t default_timer_accuracy_usec;
+ int original_log_level;
+ LogTarget original_log_target;
+ bool log_level_overridden:1;
+ bool log_target_overridden:1;
+
struct rlimit *rlimit[_RLIMIT_MAX];
/* non-zero if we are reloading or reexecuting, */
int n_reloading;
+ /* A set which contains all jobs that started before reload and finished
+ * during it */
+ Set *pending_finished_jobs;
unsigned n_installed_jobs;
unsigned n_failed_jobs;
@@ -380,8 +380,8 @@ struct Manager {
int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **m);
Manager* manager_free(Manager *m);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
-void manager_enumerate(Manager *m);
int manager_startup(Manager *m, FILE *serialization, FDSet *fds);
Job *manager_get_job(Manager *m, uint32_t id);
@@ -391,6 +391,7 @@ 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, sd_bus_error *e, Unit **_ret);
int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
+int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret);
@@ -463,6 +464,12 @@ char *manager_taint_string(Manager *m);
void manager_ref_console(Manager *m);
void manager_unref_console(Manager *m);
+void manager_override_log_level(Manager *m, int level);
+void manager_restore_original_log_level(Manager *m);
+
+void manager_override_log_target(Manager *m, LogTarget target);
+void manager_restore_original_log_target(Manager *m);
+
const char *manager_state_to_string(ManagerState m) _const_;
ManagerState manager_state_from_string(const char *s) _pure_;
diff --git a/src/core/meson.build b/src/core/meson.build
index 3fc43f6335..3852c5e9d8 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
libcore_la_sources = '''
audit-fd.c
@@ -140,7 +125,7 @@ load_fragment_gperf_gperf = custom_target(
'load-fragment-gperf.gperf',
input : 'load-fragment-gperf.gperf.m4',
output: 'load-fragment-gperf.gperf',
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true)
load_fragment_gperf_c = custom_target(
@@ -163,13 +148,14 @@ libcore = static_library(
load_fragment_gperf_c,
load_fragment_gperf_nulstr_c,
include_directories : includes,
- link_with : [libshared_static],
dependencies : [threads,
+ librt,
libseccomp,
libpam,
libaudit,
libkmod,
libapparmor,
+ libselinux,
libmount])
systemd_sources = files('main.c')
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index 1ecf5c0d9f..16880e6157 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <ftw.h>
@@ -48,10 +30,10 @@
#include "virt.h"
typedef enum MountMode {
- MNT_NONE = 0,
- MNT_FATAL = 1 << 0,
- MNT_IN_CONTAINER = 1 << 1,
- MNT_CHECK_WRITABLE = 1 << 2,
+ MNT_NONE = 0,
+ MNT_FATAL = 1 << 0,
+ MNT_IN_CONTAINER = 1 << 1,
+ MNT_CHECK_WRITABLE = 1 << 2,
} MountMode;
typedef struct MountPoint {
@@ -169,7 +151,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
/* Relabel first, just in case */
if (relabel)
- (void) label_fix(p->where, true, true);
+ (void) label_fix(p->where, LABEL_IGNORE_ENOENT|LABEL_IGNORE_EROFS);
r = path_is_mount_point(p->where, NULL, AT_SYMLINK_FOLLOW);
if (r < 0 && r != -ENOENT) {
@@ -207,7 +189,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
/* Relabel again, since we now mounted something fresh here */
if (relabel)
- (void) label_fix(p->where, false, false);
+ (void) label_fix(p->where, 0);
if (p->mode & MNT_CHECK_WRITABLE) {
if (access(p->where, W_OK) < 0) {
@@ -292,7 +274,7 @@ int mount_cgroup_controllers(char ***join_controllers) {
if (strv_find(*k, controller))
break;
- if (k && *k) {
+ if (*k) {
char **i, **j;
for (i = *k, j = *k; *i; i++) {
@@ -316,10 +298,8 @@ int mount_cgroup_controllers(char ***join_controllers) {
options = strv_join(*k, ",");
if (!options)
return log_oom();
- } else {
- options = controller;
- controller = NULL;
- }
+ } else
+ options = TAKE_PTR(controller);
where = strappend("/sys/fs/cgroup/", options);
if (!where)
@@ -332,7 +312,7 @@ int mount_cgroup_controllers(char ***join_controllers) {
if (r < 0)
return r;
- if (r > 0 && k && *k) {
+ if (r > 0 && *k) {
char **i;
for (i = *k; *i; i++) {
@@ -377,7 +357,7 @@ static int nftw_cb(
if (_unlikely_(ftwbuf->level == 0))
return FTW_CONTINUE;
- label_fix(fpath, false, false);
+ (void) label_fix(fpath, 0);
/* /run/initramfs is static data and big, no need to
* dynamically relabel its contents at boot... */
@@ -399,19 +379,18 @@ static int relabel_cgroup_filesystems(void) {
only when the filesystem has been already populated by a previous instance of systemd
running from initrd. Otherwise don't remount anything and leave the filesystem read-write
for the cgroup filesystems to be mounted inside. */
- r = statfs("/sys/fs/cgroup", &st);
- if (r < 0) {
+ if (statfs("/sys/fs/cgroup", &st) < 0)
return log_error_errno(errno, "Failed to determine mount flags for /sys/fs/cgroup: %m");
- }
if (st.f_flags & ST_RDONLY)
(void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL);
- label_fix("/sys/fs/cgroup", false, false);
- nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+ (void) label_fix("/sys/fs/cgroup", 0);
+ (void) nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
if (st.f_flags & ST_RDONLY)
(void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL);
+
} else if (r < 0)
return log_error_errno(r, "Failed to determine whether we are in all unified mode: %m");
@@ -437,9 +416,9 @@ int mount_setup(bool loaded_policy) {
before_relabel = now(CLOCK_MONOTONIC);
- nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
- nftw("/dev/shm", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
- nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+ (void) nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+ (void) nftw("/dev/shm", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+ (void) nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
r = relabel_cgroup_filesystems();
if (r < 0)
@@ -473,14 +452,20 @@ int mount_setup(bool loaded_policy) {
(void) mkdir_label("/run/systemd", 0755);
(void) mkdir_label("/run/systemd/system", 0755);
- /* Set up inaccessible items */
+ /* Set up inaccessible (and empty) file nodes of all types */
(void) mkdir_label("/run/systemd/inaccessible", 0000);
(void) mknod("/run/systemd/inaccessible/reg", S_IFREG | 0000, 0);
(void) mkdir_label("/run/systemd/inaccessible/dir", 0000);
- (void) mknod("/run/systemd/inaccessible/chr", S_IFCHR | 0000, makedev(0, 0));
- (void) mknod("/run/systemd/inaccessible/blk", S_IFBLK | 0000, makedev(0, 0));
(void) mkfifo("/run/systemd/inaccessible/fifo", 0000);
(void) mknod("/run/systemd/inaccessible/sock", S_IFSOCK | 0000, 0);
+ /* The following two are likely to fail if we lack the privs for it (for example in an userns environment, if
+ * CAP_SYS_MKNOD is missing, or if a device node policy prohibit major/minor of 0 device nodes to be
+ * created). But that's entirely fine. Consumers of these files should carry fallback to use a different node
+ * then, for example /run/systemd/inaccessible/sock, which is close enough in behaviour and semantics for most
+ * uses. */
+ (void) mknod("/run/systemd/inaccessible/chr", S_IFCHR | 0000, makedev(0, 0));
+ (void) mknod("/run/systemd/inaccessible/blk", S_IFBLK | 0000, makedev(0, 0));
+
return 0;
}
diff --git a/src/core/mount-setup.h b/src/core/mount-setup.h
index 2c96e64e52..43cd8908de 100644
--- a/src/core/mount-setup.h
+++ b/src/core/mount-setup.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
int mount_setup_early(void);
diff --git a/src/core/mount.c b/src/core/mount.c
index fb55c71d3c..21437dad08 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <signal.h>
@@ -29,6 +11,7 @@
#include "alloc-util.h"
#include "dbus-mount.h"
+#include "device.h"
#include "escape.h"
#include "exit-status.h"
#include "format-util.h"
@@ -529,23 +512,23 @@ static int mount_verify(Mount *m) {
if (!unit_has_name(UNIT(m), e)) {
log_unit_error(UNIT(m), "Where= setting doesn't match unit name. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
log_unit_error(UNIT(m), "Cannot create mount unit for API file system %s. Refusing.", m->where);
- return -EINVAL;
+ return -ENOEXEC;
}
p = get_mount_parameters_fragment(m);
if (p && !p->what) {
log_unit_error(UNIT(m), "What= setting is missing. Refusing.");
- return -EBADMSG;
+ return -ENOEXEC;
}
if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) {
log_unit_error(UNIT(m), "Unit has PAM enabled. Kill mode must be set to control-group'. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
return 0;
@@ -566,7 +549,7 @@ static int mount_add_extras(Mount *m) {
return r;
}
- path_kill_slashes(m->where);
+ path_simplify(m->where, false);
if (!u->description) {
r = unit_set_description(u, m->where);
@@ -669,7 +652,8 @@ static void mount_set_state(Mount *m, MountState state) {
if (state != old_state)
log_unit_debug(UNIT(m), "Changed %s -> %s", mount_state_to_string(old_state), mount_state_to_string(state));
- unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
+ unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state],
+ m->reload_result == MOUNT_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE);
}
static int mount_coldplug(Unit *u) {
@@ -1610,11 +1594,8 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
assert(m);
t = mnt_new_table();
- if (!t)
- return log_oom();
-
i = mnt_new_iter(MNT_ITER_FORWARD);
- if (!i)
+ if (!t || !i)
return log_oom();
r = mnt_table_parse_mtab(t, NULL);
@@ -1623,9 +1604,9 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
r = 0;
for (;;) {
+ struct libmnt_fs *fs;
const char *device, *path, *options, *fstype;
_cleanup_free_ char *d = NULL, *p = NULL;
- struct libmnt_fs *fs;
int k;
k = mnt_table_next_fs(t, i, &fs);
@@ -1648,7 +1629,7 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
if (cunescape(path, UNESCAPE_RELAX, &p) < 0)
return log_oom();
- (void) device_found_node(m, d, true, DEVICE_FOUND_MOUNT, set_flags);
+ device_found_node(m, d, DEVICE_FOUND_MOUNT, DEVICE_FOUND_MOUNT);
k = mount_setup_unit(m, d, p, options, fstype, set_flags);
if (r == 0 && k < 0)
@@ -1685,7 +1666,7 @@ static int mount_get_timeout(Unit *u, usec_t *timeout) {
return 1;
}
-static int synthesize_root_mount(Manager *m) {
+static void mount_enumerate_perpetual(Manager *m) {
Unit *u;
int r;
@@ -1697,8 +1678,10 @@ static int synthesize_root_mount(Manager *m) {
u = manager_get_unit(m, SPECIAL_ROOT_MOUNT);
if (!u) {
r = unit_new_for_name(m, sizeof(Mount), SPECIAL_ROOT_MOUNT, &u);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate the special " SPECIAL_ROOT_MOUNT " unit: %m");
+ if (r < 0) {
+ log_error_errno(r, "Failed to allocate the special " SPECIAL_ROOT_MOUNT " unit: %m");
+ return;
+ }
}
u->perpetual = true;
@@ -1706,8 +1689,6 @@ static int synthesize_root_mount(Manager *m) {
unit_add_to_load_queue(u);
unit_add_to_dbus_queue(u);
-
- return 0;
}
static bool mount_is_mounted(Mount *m) {
@@ -1721,10 +1702,6 @@ static void mount_enumerate(Manager *m) {
assert(m);
- r = synthesize_root_mount(m);
- if (r < 0)
- goto fail;
-
mnt_init_debug(0);
if (!m->mount_monitor) {
@@ -1910,7 +1887,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
continue;
/* Let the device units know that the device is no longer mounted */
- (void) device_found_node(m, what, false, DEVICE_FOUND_MOUNT, true);
+ device_found_node(m, what, 0, DEVICE_FOUND_MOUNT);
}
return 0;
@@ -2015,6 +1992,7 @@ const UnitVTable mount_vtable = {
.can_transient = true,
+ .enumerate_perpetual = mount_enumerate_perpetual,
.enumerate = mount_enumerate,
.shutdown = mount_shutdown,
diff --git a/src/core/mount.h b/src/core/mount.h
index 1a496def84..67ab8ecf93 100644
--- a/src/core/mount.h
+++ b/src/core/mount.h
@@ -1,29 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Mount Mount;
#include "kill.h"
#include "dynamic-user.h"
+#include "unit.h"
typedef enum MountExecCommand {
MOUNT_EXEC_MOUNT,
@@ -110,3 +92,5 @@ MountExecCommand mount_exec_command_from_string(const char *s) _pure_;
const char* mount_result_to_string(MountResult i) _const_;
MountResult mount_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(MOUNT, Mount);
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 0e9c7b8fb4..e4930db15c 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <sched.h>
@@ -74,16 +56,18 @@ typedef struct MountEntry {
bool ignore:1; /* Ignore if path does not exist? */
bool has_prefix:1; /* Already is prefixed by the root dir? */
bool read_only:1; /* Shall this mount point be read-only? */
+ bool applied:1; /* Already applied */
char *path_malloc; /* Use this instead of 'path_const' if we had to allocate memory */
const char *source_const; /* The source path, for bind mounts */
char *source_malloc;
const char *options_const;/* Mount options for tmpfs */
char *options_malloc;
unsigned long flags; /* Mount flags used by EMPTY_DIR and TMPFS. Do not include MS_RDONLY here, but please use read_only. */
+ unsigned n_followed;
} MountEntry;
/* If MountAPIVFS= is used, let's mount /sys and /proc into the it, but only as a fallback if the user hasn't mounted
- * something there already. These mounts are hence overriden by any other explicitly configured mounts. */
+ * something there already. These mounts are hence overridden by any other explicitly configured mounts. */
static const MountEntry apivfs_table[] = {
{ "/proc", PROCFS, false },
{ "/dev", BIND_DEV, false },
@@ -92,23 +76,26 @@ static const MountEntry apivfs_table[] = {
/* ProtectKernelTunables= option and the related filesystem APIs */
static const MountEntry protect_kernel_tunables_table[] = {
- { "/proc/sys", READONLY, false },
- { "/proc/sysrq-trigger", READONLY, true },
- { "/proc/latency_stats", READONLY, true },
- { "/proc/mtrr", READONLY, true },
- { "/proc/apm", READONLY, true }, /* Obsolete API, there's no point in permitting access to this, ever */
{ "/proc/acpi", READONLY, true },
- { "/proc/timer_stats", READONLY, true },
+ { "/proc/apm", READONLY, true }, /* Obsolete API, there's no point in permitting access to this, ever */
{ "/proc/asound", READONLY, true },
{ "/proc/bus", READONLY, true },
{ "/proc/fs", READONLY, true },
{ "/proc/irq", READONLY, true },
+ { "/proc/kallsyms", INACCESSIBLE, true },
+ { "/proc/kcore", INACCESSIBLE, true },
+ { "/proc/latency_stats", READONLY, true },
+ { "/proc/mtrr", READONLY, true },
+ { "/proc/scsi", READONLY, true },
+ { "/proc/sys", READONLY, false },
+ { "/proc/sysrq-trigger", READONLY, true },
+ { "/proc/timer_stats", READONLY, true },
{ "/sys", READONLY, false },
- { "/sys/kernel/debug", READONLY, true },
- { "/sys/kernel/tracing", READONLY, true },
{ "/sys/fs/bpf", READONLY, true },
{ "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */
{ "/sys/fs/selinux", READWRITE, true },
+ { "/sys/kernel/debug", READONLY, true },
+ { "/sys/kernel/tracing", READONLY, true },
};
/* ProtectKernelModules= option */
@@ -286,8 +273,8 @@ static int append_empty_dir_mounts(MountEntry **p, char **strv) {
return 0;
}
-static int append_bind_mounts(MountEntry **p, const BindMount *binds, unsigned n) {
- unsigned i;
+static int append_bind_mounts(MountEntry **p, const BindMount *binds, size_t n) {
+ size_t i;
assert(p);
@@ -306,8 +293,8 @@ static int append_bind_mounts(MountEntry **p, const BindMount *binds, unsigned n
return 0;
}
-static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs, unsigned n) {
- unsigned i;
+static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs, size_t n) {
+ size_t i;
int r;
assert(p);
@@ -330,7 +317,7 @@ static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs,
if (r < 0)
return r;
- ro = !!(flags & MS_RDONLY);
+ ro = flags & MS_RDONLY;
if (ro)
flags ^= MS_RDONLY;
}
@@ -349,8 +336,8 @@ static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs,
return 0;
}
-static int append_static_mounts(MountEntry **p, const MountEntry *mounts, unsigned n, bool ignore_protect) {
- unsigned i;
+static int append_static_mounts(MountEntry **p, const MountEntry *mounts, size_t n, bool ignore_protect) {
+ size_t i;
assert(p);
assert(mounts);
@@ -423,15 +410,14 @@ static int mount_path_compare(const void *a, const void *b) {
/* If the paths are equal, check the mode */
if (p->mode < q->mode)
return -1;
-
if (p->mode > q->mode)
return 1;
return 0;
}
-static int prefix_where_needed(MountEntry *m, unsigned n, const char *root_directory) {
- unsigned i;
+static int prefix_where_needed(MountEntry *m, size_t n, const char *root_directory) {
+ size_t i;
/* Prefixes all paths in the bind mount table with the root directory if it is specified and the entry needs
* that. */
@@ -456,7 +442,7 @@ static int prefix_where_needed(MountEntry *m, unsigned n, const char *root_direc
return 0;
}
-static void drop_duplicates(MountEntry *m, unsigned *n) {
+static void drop_duplicates(MountEntry *m, size_t *n) {
MountEntry *f, *t, *previous;
assert(m);
@@ -467,8 +453,10 @@ static void drop_duplicates(MountEntry *m, unsigned *n) {
for (f = m, t = m, previous = NULL; f < m + *n; f++) {
/* The first one wins (which is the one with the more restrictive mode), see mount_path_compare()
- * above. */
- if (previous && path_equal(mount_entry_path(f), mount_entry_path(previous))) {
+ * above. Note that we only drop duplicates that haven't been mounted yet. */
+ if (previous &&
+ path_equal(mount_entry_path(f), mount_entry_path(previous)) &&
+ !f->applied && !previous->applied) {
log_debug("%s is duplicate.", mount_entry_path(f));
previous->read_only = previous->read_only || mount_entry_read_only(f); /* Propagate the read-only flag to the remaining entry */
mount_entry_done(f);
@@ -483,7 +471,7 @@ static void drop_duplicates(MountEntry *m, unsigned *n) {
*n = t - m;
}
-static void drop_inaccessible(MountEntry *m, unsigned *n) {
+static void drop_inaccessible(MountEntry *m, size_t *n) {
MountEntry *f, *t;
const char *clear = NULL;
@@ -512,7 +500,7 @@ static void drop_inaccessible(MountEntry *m, unsigned *n) {
*n = t - m;
}
-static void drop_nop(MountEntry *m, unsigned *n) {
+static void drop_nop(MountEntry *m, size_t *n) {
MountEntry *f, *t;
assert(m);
@@ -551,7 +539,7 @@ static void drop_nop(MountEntry *m, unsigned *n) {
*n = t - m;
}
-static void drop_outside_root(const char *root_directory, MountEntry *m, unsigned *n) {
+static void drop_outside_root(const char *root_directory, MountEntry *m, size_t *n) {
MountEntry *f, *t;
assert(m);
@@ -578,14 +566,14 @@ static void drop_outside_root(const char *root_directory, MountEntry *m, unsigne
*n = t - m;
}
-static int clone_device_node(const char *d, const char *temporary_mount) {
+static int clone_device_node(const char *d, const char *temporary_mount, bool *make_devnode) {
const char *dn;
struct stat st;
int r;
if (stat(d, &st) < 0) {
if (errno == ENOENT)
- return 0;
+ return -ENXIO;
return -errno;
}
@@ -594,17 +582,41 @@ static int clone_device_node(const char *d, const char *temporary_mount) {
return -EINVAL;
if (st.st_rdev == 0)
- return 0;
+ return -ENXIO;
dn = strjoina(temporary_mount, d);
- mac_selinux_create_file_prepare(d, st.st_mode);
- r = mknod(dn, st.st_mode, st.st_rdev);
+ if (*make_devnode) {
+ mac_selinux_create_file_prepare(d, st.st_mode);
+ r = mknod(dn, st.st_mode, st.st_rdev);
+ mac_selinux_create_file_clear();
+
+ if (r == 0)
+ return 0;
+ if (errno != EPERM)
+ return log_debug_errno(errno, "mknod failed for %s: %m", d);
+
+ *make_devnode = false;
+ }
+
+ /* We're about to fallback to bind-mounting the device
+ * node. So create a dummy bind-mount target. */
+ mac_selinux_create_file_prepare(d, 0);
+ r = mknod(dn, S_IFREG, 0);
mac_selinux_create_file_clear();
- if (r < 0)
- return log_debug_errno(errno, "mknod failed for %s: %m", d);
- return 1;
+ if (r < 0 && errno != EEXIST)
+ return log_debug_errno(errno, "mknod fallback failed for %s: %m", d);
+
+ /* Fallback to bind-mounting:
+ * The assumption here is that all used device nodes carry standard
+ * properties. Specifically, the devices nodes we bind-mount should
+ * either be owned by root:root or root:tty (e.g. /dev/tty, /dev/ptmx)
+ * and should not carry ACLs. */
+ if (mount(d, dn, NULL, MS_BIND, NULL) < 0)
+ return log_debug_errno(errno, "mount failed for %s: %m", d);
+
+ return 0;
}
static int mount_private_dev(MountEntry *m) {
@@ -618,6 +630,7 @@ static int mount_private_dev(MountEntry *m) {
char temporary_mount[] = "/tmp/namespace-dev-XXXXXX";
const char *d, *dev = NULL, *devpts = NULL, *devshm = NULL, *devhugepages = NULL, *devmqueue = NULL, *devlog = NULL, *devptmx = NULL;
+ bool can_mknod = true;
_cleanup_umask_ mode_t u;
int r;
@@ -658,13 +671,9 @@ static int mount_private_dev(MountEntry *m) {
goto fail;
}
} else {
- r = clone_device_node("/dev/ptmx", temporary_mount);
+ r = clone_device_node("/dev/ptmx", temporary_mount, &can_mknod);
if (r < 0)
goto fail;
- if (r == 0) {
- r = -ENXIO;
- goto fail;
- }
}
devshm = strjoina(temporary_mount, "/dev/shm");
@@ -687,8 +696,9 @@ static int mount_private_dev(MountEntry *m) {
(void) symlink("/run/systemd/journal/dev-log", devlog);
NULSTR_FOREACH(d, devnodes) {
- r = clone_device_node(d, temporary_mount);
- if (r < 0)
+ r = clone_device_node(d, temporary_mount, &can_mknod);
+ /* ENXIO means the the *source* is not a device file, skip creation in that case */
+ if (r < 0 && r != -ENXIO)
goto fail;
}
@@ -808,36 +818,37 @@ static int mount_tmpfs(const MountEntry *m) {
return 1;
}
-static int mount_entry_chase(
+static int follow_symlink(
const char *root_directory,
- const MountEntry *m,
- const char *path,
- bool chase_nonexistent,
- char **location) {
+ MountEntry *m) {
- char *chased;
+ _cleanup_free_ char *target = NULL;
int r;
- assert(m);
+ /* Let's chase symlinks, but only one step at a time. That's because depending where the symlink points we
+ * might need to change the order in which we mount stuff. Hence: let's normalize piecemeal, and do one step at
+ * a time by specifying CHASE_STEP. This function returns 0 if we resolved one step, and > 0 if we reached the
+ * end and already have a fully normalized name. */
- /* Since mount() will always follow symlinks and we need to take the different root directory into account we
- * chase the symlinks on our own first. This is called for the destination path, as well as the source path (if
- * that applies). The result is stored in "location". */
+ r = chase_symlinks(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to chase symlinks '%s': %m", mount_entry_path(m));
+ if (r > 0) /* Reached the end, nothing more to resolve */
+ return 1;
- r = chase_symlinks(path, root_directory, chase_nonexistent ? CHASE_NONEXISTENT : 0, &chased);
- if (r == -ENOENT && m->ignore) {
- log_debug_errno(r, "Path %s does not exist, ignoring.", path);
- return 0;
+ if (m->n_followed >= CHASE_SYMLINKS_MAX) { /* put a boundary on things */
+ log_debug("Symlink loop on '%s'.", mount_entry_path(m));
+ return -ELOOP;
}
- if (r < 0)
- return log_debug_errno(r, "Failed to follow symlinks on %s: %m", path);
- log_debug("Followed symlinks %s → %s.", path, chased);
+ log_debug("Followed mount entry path symlink %s → %s.", mount_entry_path(m), target);
- free(*location);
- *location = chased;
+ free_and_replace(m->path_malloc, target);
+ m->has_prefix = true;
- return 1;
+ m->n_followed ++;
+
+ return 0;
}
static int apply_mount(
@@ -850,10 +861,6 @@ static int apply_mount(
assert(m);
- r = mount_entry_chase(root_directory, m, mount_entry_path(m), !IN_SET(m->mode, INACCESSIBLE, READONLY, READWRITE), &m->path_malloc);
- if (r <= 0)
- return r;
-
log_debug("Applying namespace mount on %s", mount_entry_path(m));
switch (m->mode) {
@@ -866,8 +873,12 @@ static int apply_mount(
* inaccessible path. */
(void) umount_recursive(mount_entry_path(m), 0);
- if (lstat(mount_entry_path(m), &target) < 0)
+ if (lstat(mount_entry_path(m), &target) < 0) {
+ if (errno == ENOENT && m->ignore)
+ return 0;
+
return log_debug_errno(errno, "Failed to lstat() %s to determine what to mount over it: %m", mount_entry_path(m));
+ }
what = mode_to_inaccessible_node(target.st_mode);
if (!what) {
@@ -880,6 +891,8 @@ static int apply_mount(
case READONLY:
case READWRITE:
r = path_is_mount_point(mount_entry_path(m), root_directory, 0);
+ if (r == -ENOENT && m->ignore)
+ return 0;
if (r < 0)
return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", mount_entry_path(m));
if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY bit for the mount point if needed. */
@@ -892,16 +905,29 @@ static int apply_mount(
rbind = false;
_fallthrough_;
- case BIND_MOUNT_RECURSIVE:
- /* Also chase the source mount */
+ case BIND_MOUNT_RECURSIVE: {
+ _cleanup_free_ char *chased = NULL;
- r = mount_entry_chase(root_directory, m, mount_entry_source(m), false, &m->source_malloc);
- if (r <= 0)
- return r;
+ /* Since mount() will always follow symlinks we chase the symlinks on our own first. Note that bind
+ * mount source paths are always relative to the host root, hence we pass NULL as root directory to
+ * chase_symlinks() here. */
+
+ r = chase_symlinks(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased);
+ if (r == -ENOENT && m->ignore) {
+ log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m));
+ return 0;
+ }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to follow symlinks on %s: %m", mount_entry_source(m));
+
+ log_debug("Followed source symlinks %s → %s.", mount_entry_source(m), chased);
+
+ free_and_replace(m->source_malloc, chased);
what = mount_entry_source(m);
make = true;
break;
+ }
case EMPTY_DIR:
case TMPFS:
@@ -939,14 +965,22 @@ static int apply_mount(
/* Hmm, either the source or the destination are missing. Let's see if we can create the destination, then try again */
- if (stat(what, &st) >= 0) {
+ if (stat(what, &st) < 0)
+ log_debug_errno(errno, "Mount point source '%s' is not accessible: %m", what);
+ else {
+ int q;
(void) mkdir_parents(mount_entry_path(m), 0755);
if (S_ISDIR(st.st_mode))
- try_again = mkdir(mount_entry_path(m), 0755) >= 0;
+ q = mkdir(mount_entry_path(m), 0755) < 0 ? -errno : 0;
+ else
+ q = touch(mount_entry_path(m));
+
+ if (q < 0)
+ log_debug_errno(q, "Failed to create destination mount point node '%s': %m", mount_entry_path(m));
else
- try_again = touch(mount_entry_path(m)) >= 0;
+ try_again = true;
}
}
@@ -1011,22 +1045,22 @@ static bool namespace_info_mount_apivfs(const char *root_directory, const Namesp
ns_info->protect_kernel_tunables);
}
-static unsigned namespace_calculate_mounts(
+static size_t namespace_calculate_mounts(
const char* root_directory,
const NamespaceInfo *ns_info,
char** read_write_paths,
char** read_only_paths,
char** inaccessible_paths,
char** empty_directories,
- unsigned n_bind_mounts,
- unsigned n_temporary_filesystems,
+ size_t n_bind_mounts,
+ size_t n_temporary_filesystems,
const char* tmp_dir,
const char* var_tmp_dir,
ProtectHome protect_home,
ProtectSystem protect_system) {
- unsigned protect_home_cnt;
- unsigned protect_system_cnt =
+ size_t protect_home_cnt;
+ size_t protect_system_cnt =
(protect_system == PROTECT_SYSTEM_STRICT ?
ELEMENTSOF(protect_system_strict_table) :
((protect_system == PROTECT_SYSTEM_FULL) ?
@@ -1057,6 +1091,18 @@ static unsigned namespace_calculate_mounts(
(namespace_info_mount_apivfs(root_directory, ns_info) ? ELEMENTSOF(apivfs_table) : 0);
}
+static void normalize_mounts(const char *root_directory, MountEntry *mounts, size_t *n_mounts) {
+ assert(n_mounts);
+ assert(mounts || *n_mounts == 0);
+
+ qsort_safe(mounts, *n_mounts, sizeof(MountEntry), mount_path_compare);
+
+ drop_duplicates(mounts, n_mounts);
+ drop_outside_root(root_directory, mounts, n_mounts);
+ drop_inaccessible(mounts, n_mounts);
+ drop_nop(mounts, n_mounts);
+}
+
int setup_namespace(
const char* root_directory,
const char* root_image,
@@ -1066,9 +1112,9 @@ int setup_namespace(
char** inaccessible_paths,
char** empty_directories,
const BindMount *bind_mounts,
- unsigned n_bind_mounts,
+ size_t n_bind_mounts,
const TemporaryFileSystem *temporary_filesystems,
- unsigned n_temporary_filesystems,
+ size_t n_temporary_filesystems,
const char* tmp_dir,
const char* var_tmp_dir,
ProtectHome protect_home,
@@ -1082,9 +1128,9 @@ int setup_namespace(
_cleanup_free_ void *root_hash = NULL;
MountEntry *m, *mounts = NULL;
size_t root_hash_size = 0;
- bool make_slave = false;
const char *root;
- unsigned n_mounts;
+ size_t n_mounts;
+ bool make_slave;
bool require_prefix = false;
int r = 0;
@@ -1096,7 +1142,9 @@ int setup_namespace(
if (root_image) {
dissect_image_flags |= DISSECT_IMAGE_REQUIRE_ROOT;
- if (protect_system == PROTECT_SYSTEM_STRICT && strv_isempty(read_write_paths))
+ if (protect_system == PROTECT_SYSTEM_STRICT &&
+ protect_home != PROTECT_HOME_NO &&
+ strv_isempty(read_write_paths))
dissect_image_flags |= DISSECT_IMAGE_READ_ONLY;
r = loop_device_make_by_path(root_image,
@@ -1120,19 +1168,17 @@ int setup_namespace(
if (root_directory)
root = root_directory;
- else if (root_image || n_bind_mounts > 0 || n_temporary_filesystems > 0) {
-
- /* If we are booting from an image, create a mount point for the image, if it's still missing. We use
- * the same mount point for all images, which is safe, since they all live in their own namespaces
- * after all, and hence won't see each other. We also use such a root directory whenever there are bind
- * mounts configured, so that their source mounts are never obstructed by mounts we already applied
- * while we are applying them. */
+ else {
+ /* Always create the mount namespace in a temporary directory, instead of operating
+ * directly in the root. The temporary directory prevents any mounts from being
+ * potentially obscured my other mounts we already applied.
+ * We use the same mount point for all images, which is safe, since they all live
+ * in their own namespaces after all, and hence won't see each other. */
root = "/run/systemd/unit-root";
(void) mkdir_label(root, 0700);
require_prefix = true;
- } else
- root = NULL;
+ }
n_mounts = namespace_calculate_mounts(
root,
@@ -1147,8 +1193,7 @@ int setup_namespace(
protect_home, protect_system);
/* Set mount slave mode */
- if (root || n_mounts > 0)
- make_slave = true;
+ make_slave = root || n_mounts > 0 || ns_info->private_mounts;
if (n_mounts > 0) {
m = mounts = (MountEntry *) alloca0(n_mounts * sizeof(MountEntry));
@@ -1239,12 +1284,7 @@ int setup_namespace(
if (r < 0)
goto finish;
- qsort(mounts, n_mounts, sizeof(MountEntry), mount_path_compare);
-
- drop_duplicates(mounts, &n_mounts);
- drop_outside_root(root, mounts, &n_mounts);
- drop_inaccessible(mounts, &n_mounts);
- drop_nop(mounts, &n_mounts);
+ normalize_mounts(root_directory, mounts, &n_mounts);
}
if (unshare(CLONE_NEWNS) < 0) {
@@ -1304,7 +1344,7 @@ int setup_namespace(
if (n_mounts > 0) {
_cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
char **blacklist;
- unsigned j;
+ size_t j;
/* Open /proc/self/mountinfo now as it may become unavailable if we mount anything on top of /proc.
* For example, this is the case with the option: 'InaccessiblePaths=/proc' */
@@ -1314,11 +1354,38 @@ int setup_namespace(
goto finish;
}
- /* First round, add in all special mounts we need */
- for (m = mounts; m < mounts + n_mounts; ++m) {
- r = apply_mount(root, m);
- if (r < 0)
- goto finish;
+ /* First round, establish all mounts we need */
+ for (;;) {
+ bool again = false;
+
+ for (m = mounts; m < mounts + n_mounts; ++m) {
+
+ if (m->applied)
+ continue;
+
+ r = follow_symlink(root, m);
+ if (r < 0)
+ goto finish;
+ if (r == 0) {
+ /* We hit a symlinked mount point. The entry got rewritten and might point to a
+ * very different place now. Let's normalize the changed list, and start from
+ * the beginning. After all to mount the entry at the new location we might
+ * need some other mounts first */
+ again = true;
+ break;
+ }
+
+ r = apply_mount(root, m);
+ if (r < 0)
+ goto finish;
+
+ m->applied = true;
+ }
+
+ if (!again)
+ break;
+
+ normalize_mounts(root_directory, mounts, &n_mounts);
}
/* Create a blacklist we can pass to bind_mount_recursive() */
@@ -1359,8 +1426,8 @@ finish:
return r;
}
-void bind_mount_free_many(BindMount *b, unsigned n) {
- unsigned i;
+void bind_mount_free_many(BindMount *b, size_t n) {
+ size_t i;
assert(b || n == 0);
@@ -1372,7 +1439,7 @@ void bind_mount_free_many(BindMount *b, unsigned n) {
free(b);
}
-int bind_mount_add(BindMount **b, unsigned *n, const BindMount *item) {
+int bind_mount_add(BindMount **b, size_t *n, const BindMount *item) {
_cleanup_free_ char *s = NULL, *d = NULL;
BindMount *c;
@@ -1395,19 +1462,18 @@ int bind_mount_add(BindMount **b, unsigned *n, const BindMount *item) {
*b = c;
c[(*n) ++] = (BindMount) {
- .source = s,
- .destination = d,
+ .source = TAKE_PTR(s),
+ .destination = TAKE_PTR(d),
.read_only = item->read_only,
.recursive = item->recursive,
.ignore_enoent = item->ignore_enoent,
};
- s = d = NULL;
return 0;
}
-void temporary_filesystem_free_many(TemporaryFileSystem *t, unsigned n) {
- unsigned i;
+void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n) {
+ size_t i;
assert(t || n == 0);
@@ -1421,7 +1487,7 @@ void temporary_filesystem_free_many(TemporaryFileSystem *t, unsigned n) {
int temporary_filesystem_add(
TemporaryFileSystem **t,
- unsigned *n,
+ size_t *n,
const char *path,
const char *options) {
@@ -1449,11 +1515,10 @@ int temporary_filesystem_add(
*t = c;
c[(*n) ++] = (TemporaryFileSystem) {
- .path = p,
- .options = o,
+ .path = TAKE_PTR(p),
+ .options = TAKE_PTR(o),
};
- p = o = NULL;
return 0;
}
@@ -1491,8 +1556,7 @@ static int setup_one_tmp_dir(const char *id, const char *prefix, char **path) {
return -errno;
}
- *path = x;
- x = NULL;
+ *path = TAKE_PTR(x);
return 0;
}
@@ -1608,19 +1672,7 @@ static const char *const protect_home_table[_PROTECT_HOME_MAX] = {
[PROTECT_HOME_TMPFS] = "tmpfs",
};
-DEFINE_STRING_TABLE_LOOKUP(protect_home, ProtectHome);
-
-ProtectHome parse_protect_home_or_bool(const char *s) {
- int r;
-
- r = parse_boolean(s);
- if (r > 0)
- return PROTECT_HOME_YES;
- if (r == 0)
- return PROTECT_HOME_NO;
-
- return protect_home_from_string(s);
-}
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(protect_home, ProtectHome, PROTECT_HOME_YES);
static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = {
[PROTECT_SYSTEM_NO] = "no",
@@ -1629,19 +1681,7 @@ static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = {
[PROTECT_SYSTEM_STRICT] = "strict",
};
-DEFINE_STRING_TABLE_LOOKUP(protect_system, ProtectSystem);
-
-ProtectSystem parse_protect_system_or_bool(const char *s) {
- int r;
-
- r = parse_boolean(s);
- if (r > 0)
- return PROTECT_SYSTEM_YES;
- if (r == 0)
- return PROTECT_SYSTEM_NO;
-
- return protect_system_from_string(s);
-}
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(protect_system, ProtectSystem, PROTECT_SYSTEM_YES);
static const char* const namespace_type_table[] = {
[NAMESPACE_MOUNT] = "mnt",
diff --git a/src/core/namespace.h b/src/core/namespace.h
index 3d56a7302d..1188c6d595 100644
--- a/src/core/namespace.h
+++ b/src/core/namespace.h
@@ -2,23 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2016 Djalal Harouni
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Djalal Harouni
***/
typedef struct NamespaceInfo NamespaceInfo;
@@ -63,6 +47,7 @@ typedef enum ProtectSystem {
struct NamespaceInfo {
bool ignore_protect_paths:1;
bool private_dev:1;
+ bool private_mounts:1;
bool protect_control_groups:1;
bool protect_kernel_tunables:1;
bool protect_kernel_modules:1;
@@ -91,9 +76,9 @@ int setup_namespace(
char **inaccessible_paths,
char **empty_directories,
const BindMount *bind_mounts,
- unsigned n_bind_mounts,
+ size_t n_bind_mounts,
const TemporaryFileSystem *temporary_filesystems,
- unsigned n_temporary_filesystems,
+ size_t n_temporary_filesystems,
const char *tmp_dir,
const char *var_tmp_dir,
ProtectHome protect_home,
@@ -110,17 +95,15 @@ int setup_netns(int netns_storage_socket[2]);
const char* protect_home_to_string(ProtectHome p) _const_;
ProtectHome protect_home_from_string(const char *s) _pure_;
-ProtectHome parse_protect_home_or_bool(const char *s);
const char* protect_system_to_string(ProtectSystem p) _const_;
ProtectSystem protect_system_from_string(const char *s) _pure_;
-ProtectSystem parse_protect_system_or_bool(const char *s);
-void bind_mount_free_many(BindMount *b, unsigned n);
-int bind_mount_add(BindMount **b, unsigned *n, const BindMount *item);
+void bind_mount_free_many(BindMount *b, size_t n);
+int bind_mount_add(BindMount **b, size_t *n, const BindMount *item);
-void temporary_filesystem_free_many(TemporaryFileSystem *t, unsigned n);
-int temporary_filesystem_add(TemporaryFileSystem **t, unsigned *n,
+void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n);
+int temporary_filesystem_add(TemporaryFileSystem **t, size_t *n,
const char *path, const char *options);
const char* namespace_type_to_string(NamespaceType t) _const_;
diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf
index 645c8f1659..415b3f5d84 100644
--- a/src/core/org.freedesktop.systemd1.conf
+++ b/src/core/org.freedesktop.systemd1.conf
@@ -62,6 +62,10 @@
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
+ send_member="GetUnitByControlGroup"/>
+
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
send_member="LoadUnit"/>
<allow send_destination="org.freedesktop.systemd1"
@@ -114,6 +118,10 @@
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
+ send_member="DumpByFileDescriptor"/>
+
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
send_member="ListUnitFiles"/>
<allow send_destination="org.freedesktop.systemd1"
@@ -140,6 +148,10 @@
send_interface="org.freedesktop.systemd1.Manager"
send_member="LookupDynamicUserByUID"/>
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
+ send_member="GetDynamicUsers"/>
+
<!-- Completely open to anyone: org.freedesktop.systemd1.Unit interface -->
<allow send_destination="org.freedesktop.systemd1"
diff --git a/src/core/org.freedesktop.systemd1.policy.in b/src/core/org.freedesktop.systemd1.policy.in
index 648221b85c..001408d34a 100644
--- a/src/core/org.freedesktop.systemd1.policy.in
+++ b/src/core/org.freedesktop.systemd1.policy.in
@@ -47,6 +47,7 @@
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.systemd1.reload-daemon org.freedesktop.systemd1.manage-units</annotate>
</action>
<action id="org.freedesktop.systemd1.set-environment">
diff --git a/src/core/path.c b/src/core/path.c
index 1893d8de45..68b13b610a 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <sys/epoll.h>
@@ -80,7 +62,7 @@ int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) {
(void) sd_event_source_set_description(s->event_source, "path");
- /* This function assumes the path was passed through path_kill_slashes()! */
+ /* This function assumes the path was passed through path_simplify()! */
assert(!strstr(s->path, "//"));
for (slash = strchr(s->path, '/'); ; slash = strchr(slash+1, '/')) {
@@ -302,7 +284,7 @@ static int path_verify(Path *p) {
if (!p->specs) {
log_unit_error(UNIT(p), "Path unit lacks path setting. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
return 0;
@@ -438,7 +420,7 @@ static void path_set_state(Path *p, PathState state) {
if (state != old_state)
log_unit_debug(UNIT(p), "Changed %s -> %s", path_state_to_string(old_state), path_state_to_string(state));
- unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], true);
+ unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], 0);
}
static void path_enter_waiting(Path *p, bool initial, bool recheck);
diff --git a/src/core/path.h b/src/core/path.h
index 41e31986f2..4d4b6236c2 100644
--- a/src/core/path.h
+++ b/src/core/path.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Path Path;
typedef struct PathSpec PathSpec;
@@ -92,3 +73,5 @@ PathType path_type_from_string(const char *s) _pure_;
const char* path_result_to_string(PathResult i) _const_;
PathResult path_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(PATH, Path);
diff --git a/src/core/scope.c b/src/core/scope.c
index 5b9c2bb3c4..751556fecf 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <unistd.h>
@@ -105,13 +87,15 @@ static void scope_set_state(Scope *s, ScopeState state) {
if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
- if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
+ if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED)) {
unit_unwatch_all_pids(UNIT(s));
+ unit_dequeue_rewatch_pids(UNIT(s));
+ }
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);
+ unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
}
static int scope_add_default_dependencies(Scope *s) {
@@ -144,7 +128,7 @@ static int scope_verify(Scope *s) {
!MANAGER_IS_RELOADING(UNIT(s)->manager) &&
!unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) {
log_unit_error(UNIT(s), "Scope has no PIDs. Refusing.");
- return -EINVAL;
+ return -ENOENT;
}
return 0;
@@ -225,7 +209,7 @@ static int scope_coldplug(Unit *u) {
}
if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
- unit_watch_all_pids(UNIT(s));
+ (void) unit_enqueue_rewatch_pids(u);
bus_scope_track_controller(s);
@@ -270,7 +254,12 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
if (s->result == SCOPE_SUCCESS)
s->result = f;
- unit_watch_all_pids(UNIT(s));
+ /* Before sending any signal, make sure we track all members of this cgroup */
+ (void) unit_watch_all_pids(UNIT(s));
+
+ /* Also, enqueue a job that we recheck all our PIDs a bit later, given that it's likely some processes have
+ * died now */
+ (void) unit_enqueue_rewatch_pids(UNIT(s));
/* If we have a controller set let's ask the controller nicely to terminate the scope, instead of us going
* directly into SIGTERM berserk mode */
@@ -353,6 +342,9 @@ static int scope_start(Unit *u) {
s->result = SCOPE_SUCCESS;
scope_set_state(s, SCOPE_RUNNING);
+
+ /* Start watching the PIDs currently in the scope */
+ (void) unit_enqueue_rewatch_pids(UNIT(s));
return 1;
}
@@ -468,17 +460,13 @@ static void scope_notify_cgroup_empty_event(Unit *u) {
}
static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
-
assert(u);
/* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to
* watch, under the assumption that we'll sooner or later get a SIGCHLD for them, as the original
* process we watched was probably the parent of them, and they are hence now our children. */
- unit_tidy_watch_pids(u, 0, 0);
- unit_watch_all_pids(u);
- /* If the PID set is empty now, then let's finish this off. */
- unit_synthesize_cgroup_empty_event(u);
+ (void) unit_enqueue_rewatch_pids(u);
}
static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
@@ -528,13 +516,9 @@ int scope_abandon(Scope *s) {
scope_set_state(s, SCOPE_ABANDONED);
- /* The client is no longer watching the remaining processes,
- * so let's step in here, under the assumption that the
- * remaining processes will be sooner or later reassigned to
- * us as parent. */
-
- unit_tidy_watch_pids(UNIT(s), 0, 0);
- unit_watch_all_pids(UNIT(s));
+ /* The client is no longer watching the remaining processes, so let's step in here, under the assumption that
+ * the remaining processes will be sooner or later reassigned to us as parent. */
+ (void) unit_enqueue_rewatch_pids(UNIT(s));
return 0;
}
@@ -551,7 +535,7 @@ _pure_ static const char *scope_sub_state_to_string(Unit *u) {
return scope_state_to_string(SCOPE(u)->state);
}
-static void scope_enumerate(Manager *m) {
+static void scope_enumerate_perpetual(Manager *m) {
Unit *u;
int r;
@@ -600,6 +584,7 @@ const UnitVTable scope_vtable = {
.can_transient = true,
.can_delegate = true,
+ .once_only = true,
.init = scope_init,
.load = scope_load,
@@ -632,5 +617,5 @@ const UnitVTable scope_vtable = {
.bus_set_property = bus_scope_set_property,
.bus_commit_properties = bus_scope_commit_properties,
- .enumerate = scope_enumerate,
+ .enumerate_perpetual = scope_enumerate_perpetual,
};
diff --git a/src/core/scope.h b/src/core/scope.h
index ca7c6c868f..c38afb5e5d 100644
--- a/src/core/scope.h
+++ b/src/core/scope.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Scope Scope;
#include "cgroup.h"
@@ -59,3 +40,5 @@ int scope_abandon(Scope *s);
const char* scope_result_to_string(ScopeResult i) _const_;
ScopeResult scope_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(SCOPE, Scope);
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index 475c3181c9..39e994afd7 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2012 Dan Walsh
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Dan Walsh
***/
#include "selinux-access.h"
diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h
index dd48d0654e..59f2e60c77 100644
--- a/src/core/selinux-access.h
+++ b/src/core/selinux-access.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2012 Dan Walsh
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Dan Walsh
***/
#include "sd-bus.h"
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
index 7135542106..bac1aa3ff6 100644
--- a/src/core/selinux-setup.c
+++ b/src/core/selinux-setup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
@@ -47,13 +29,15 @@ int mac_selinux_setup(bool *loaded_policy) {
usec_t before_load, after_load;
char *con;
int r;
- union selinux_callback cb;
+ static const union selinux_callback cb = {
+ .func_log = null_log,
+ };
+
bool initialized = false;
assert(loaded_policy);
/* Turn off all of SELinux' own logging, we want to do that */
- cb.func_log = null_log;
selinux_set_callback(SELINUX_CB_LOG, cb);
/* Don't load policy in the initrd if we don't appear to have
diff --git a/src/core/selinux-setup.h b/src/core/selinux-setup.h
index 410991c49f..ad0d4f65dc 100644
--- a/src/core/selinux-setup.h
+++ b/src/core/selinux-setup.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
int mac_selinux_setup(bool *loaded_policy);
diff --git a/src/core/service.c b/src/core/service.c
index df36019f62..db1356c417 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <signal.h>
@@ -396,6 +378,9 @@ static void service_done(Unit *u) {
s->bus_name_owner = mfree(s->bus_name_owner);
+ s->usb_function_descriptors = mfree(s->usb_function_descriptors);
+ s->usb_function_strings = mfree(s->usb_function_strings);
+
service_close_socket_fd(s);
s->peer = socket_peer_unref(s->peer);
@@ -553,37 +538,37 @@ static int service_verify(Service *s) {
if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]) {
log_unit_error(UNIT(s), "Service lacks both ExecStart= and ExecStop= setting. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->type != SERVICE_ONESHOT && !s->exec_command[SERVICE_EXEC_START]) {
log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START]) {
log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->type != SERVICE_ONESHOT && s->exec_command[SERVICE_EXEC_START]->command_next) {
log_unit_error(UNIT(s), "Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->type == SERVICE_ONESHOT && s->restart != SERVICE_RESTART_NO) {
log_unit_error(UNIT(s), "Service has Restart= setting other than no, which isn't allowed for Type=oneshot services. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->type == SERVICE_ONESHOT && !exit_status_set_is_empty(&s->restart_force_status)) {
log_unit_error(UNIT(s), "Service has RestartForceStatus= set, which isn't allowed for Type=oneshot services. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->type == SERVICE_DBUS && !s->bus_name) {
log_unit_error(UNIT(s), "Service is of type D-Bus but no D-Bus service name has been specified. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->bus_name && s->type != SERVICE_DBUS)
@@ -591,7 +576,7 @@ static int service_verify(Service *s) {
if (s->exec_context.pam_name && !IN_SET(s->kill_context.kill_mode, KILL_CONTROL_GROUP, KILL_MIXED)) {
log_unit_error(UNIT(s), "Service has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->usb_function_descriptors && !s->usb_function_strings)
@@ -725,10 +710,9 @@ static int service_add_extras(Service *s) {
if (r < 0)
return r;
- if (s->type == SERVICE_NOTIFY && s->notify_access == NOTIFY_NONE)
- s->notify_access = NOTIFY_MAIN;
-
- if (s->watchdog_usec > 0 && s->notify_access == NOTIFY_NONE)
+ /* If the service needs the notify socket, let's enable it automatically. */
+ if (s->notify_access == NOTIFY_NONE &&
+ (s->type == SERVICE_NOTIFY || s->watchdog_usec > 0 || s->n_fd_store_max > 0))
s->notify_access = NOTIFY_MAIN;
r = service_add_default_dependencies(s);
@@ -876,7 +860,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
if (s->n_fd_store_max > 0)
fprintf(f,
"%sFile Descriptor Store Max: %u\n"
- "%sFile Descriptor Store Current: %u\n",
+ "%sFile Descriptor Store Current: %zu\n",
prefix, s->n_fd_store_max,
prefix, s->n_fd_store);
@@ -1069,8 +1053,10 @@ static void service_set_state(Service *s, ServiceState state) {
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
}
- if (IN_SET(state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART))
+ if (IN_SET(state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) {
unit_unwatch_all_pids(UNIT(s));
+ unit_dequeue_rewatch_pids(UNIT(s));
+ }
if (!IN_SET(state,
SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
@@ -1091,7 +1077,9 @@ static void service_set_state(Service *s, ServiceState state) {
if (old_state != state)
log_unit_debug(UNIT(s), "Changed %s -> %s", service_state_to_string(old_state), service_state_to_string(state));
- unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
+ unit_notify(UNIT(s), table[old_state], table[state],
+ (s->reload_result == SERVICE_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE) |
+ (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0));
}
static usec_t service_coldplug_timeout(Service *s) {
@@ -1163,17 +1151,15 @@ static int service_coldplug(Unit *u) {
return r;
}
- if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART))
- unit_watch_all_pids(UNIT(s));
-
- if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
- service_start_watchdog(s);
-
if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) {
+ (void) unit_enqueue_rewatch_pids(u);
(void) unit_setup_dynamic_creds(u);
(void) unit_setup_exec_runtime(u);
}
+ if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
+ service_start_watchdog(s);
+
if (UNIT_ISSET(s->accept_socket)) {
Socket* socket = SOCKET(UNIT_DEREF(s->accept_socket));
@@ -1247,10 +1233,8 @@ static int service_collect_fds(Service *s,
continue;
if (!rfds) {
- rfds = cfds;
+ rfds = TAKE_PTR(cfds);
rn_socket_fds = cn_fds;
-
- cfds = NULL;
} else {
int *t;
@@ -1302,14 +1286,11 @@ static int service_collect_fds(Service *s,
rfd_names[n_fds] = NULL;
}
- *fds = rfds;
- *fd_names = rfd_names;
+ *fds = TAKE_PTR(rfds);
+ *fd_names = TAKE_PTR(rfd_names);
*n_socket_fds = rn_socket_fds;
*n_storage_fds = rn_storage_fds;
- rfds = NULL;
- rfd_names = NULL;
-
return 0;
}
@@ -1606,6 +1587,7 @@ static bool service_will_restart(Unit *u) {
return false;
if (UNIT(s)->job->type == JOB_START)
return true;
+
return false;
}
@@ -1692,7 +1674,8 @@ static void service_enter_stop_post(Service *s, ServiceResult f) {
s->result = f;
service_unwatch_control_pid(s);
- unit_watch_all_pids(UNIT(s));
+
+ (void) unit_enqueue_rewatch_pids(UNIT(s));
s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST];
if (s->control_command) {
@@ -1744,7 +1727,12 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
if (s->result == SERVICE_SUCCESS)
s->result = f;
- unit_watch_all_pids(UNIT(s));
+ /* Before sending any signal, make sure we track all members of this cgroup */
+ (void) unit_watch_all_pids(UNIT(s));
+
+ /* Also, enqueue a job that we recheck all our PIDs a bit later, given that it's likely some processes have
+ * died now */
+ (void) unit_enqueue_rewatch_pids(UNIT(s));
r = unit_kill_context(
UNIT(s),
@@ -1785,7 +1773,7 @@ fail:
static void service_enter_stop_by_notify(Service *s) {
assert(s);
- unit_watch_all_pids(UNIT(s));
+ (void) unit_enqueue_rewatch_pids(UNIT(s));
service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
@@ -1802,7 +1790,7 @@ static void service_enter_stop(Service *s, ServiceResult f) {
s->result = f;
service_unwatch_control_pid(s);
- unit_watch_all_pids(UNIT(s));
+ (void) unit_enqueue_rewatch_pids(UNIT(s));
s->control_command = s->exec_command[SERVICE_EXEC_STOP];
if (s->control_command) {
@@ -1855,10 +1843,11 @@ static void service_enter_running(Service *s, ServiceResult f) {
service_unwatch_control_pid(s);
- if (service_good(s)) {
+ if (s->result != SERVICE_SUCCESS)
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
+ else if (service_good(s)) {
- /* If there are any queued up sd_notify()
- * notifications, process them now */
+ /* If there are any queued up sd_notify() notifications, process them now */
if (s->notify_state == NOTIFY_RELOADING)
service_enter_reload_by_notify(s);
else if (s->notify_state == NOTIFY_STOPPING)
@@ -1868,9 +1857,7 @@ static void service_enter_running(Service *s, ServiceResult f) {
service_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec));
}
- } else if (f != SERVICE_SUCCESS)
- service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
- else if (s->remain_after_exit)
+ } else if (s->remain_after_exit)
service_set_state(s, SERVICE_EXITED);
else
service_enter_stop(s, SERVICE_SUCCESS);
@@ -1955,7 +1942,7 @@ static void service_enter_start(Service *s) {
/* There's no command line configured for the main command? Hmm, that is strange. This can only
* happen if the configuration changes at runtime. In this case, let's enter a failure
* state. */
- log_unit_error(UNIT(s), "There's no 'start' task anymore we could start: %m");
+ log_unit_error(UNIT(s), "There's no 'start' task anymore we could start.");
r = -ENXIO;
goto fail;
}
@@ -2084,8 +2071,7 @@ static void service_enter_restart(Service *s) {
LOG_UNIT_ID(UNIT(s)),
LOG_UNIT_INVOCATION_ID(UNIT(s)),
LOG_UNIT_MESSAGE(UNIT(s), "Scheduled restart job, restart counter is at %u.", s->n_restarts),
- "N_RESTARTS=%u", s->n_restarts,
- NULL);
+ "N_RESTARTS=%u", s->n_restarts);
/* Notify clients about changed restart counter */
unit_add_to_dbus_queue(UNIT(s));
@@ -2551,8 +2537,7 @@ static int service_deserialize_exec_command(Unit *u, const char *key, const char
state = STATE_EXEC_COMMAND_PATH;
break;
case STATE_EXEC_COMMAND_PATH:
- path = arg;
- arg = NULL;
+ path = TAKE_PTR(arg);
state = STATE_EXEC_COMMAND_ARGS;
if (!path_is_absolute(path))
@@ -2904,7 +2889,7 @@ static int service_demand_pid_file(Service *s) {
return -ENOMEM;
}
- path_kill_slashes(ps->path);
+ path_simplify(ps->path, false);
/* PATH_CHANGED would not be enough. There are daemons (sendmail) that
* keep their PID file open all the time. */
@@ -3083,8 +3068,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
"EXIT_CODE=%s", sigchld_code_to_string(code),
"EXIT_STATUS=%i", status,
LOG_UNIT_ID(u),
- LOG_UNIT_INVOCATION_ID(u),
- NULL);
+ LOG_UNIT_INVOCATION_ID(u));
if (s->result == SERVICE_SUCCESS)
s->result = f;
@@ -3226,7 +3210,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
* The PID file might actually be created by a START_POST
* script. In that case don't worry if the loading fails. */
- has_start_post = !!s->exec_command[SERVICE_EXEC_START_POST];
+ has_start_post = s->exec_command[SERVICE_EXEC_START_POST];
r = service_load_pid_file(s, !has_start_post);
if (!has_start_post && r < 0) {
r = service_demand_pid_file(s);
@@ -3307,11 +3291,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
/* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to watch,
* under the assumption that we'll sooner or later get a SIGCHLD for them, as the original process we watched
* was probably the parent of them, and they are hence now our children. */
- unit_tidy_watch_pids(u, s->main_pid, s->control_pid);
- unit_watch_all_pids(u);
-
- /* If the PID set is empty now, then let's check if the cgroup is empty too and finish off the unit. */
- unit_synthesize_cgroup_empty_event(u);
+ (void) unit_enqueue_rewatch_pids(u);
}
static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
@@ -3397,10 +3377,15 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
break;
case SERVICE_AUTO_RESTART:
- log_unit_info(UNIT(s),
- s->restart_usec > 0 ?
- "Service hold-off time over, scheduling restart." :
- "Service has no hold-off time, scheduling restart.");
+ if (s->restart_usec > 0) {
+ char buf_restart[FORMAT_TIMESPAN_MAX];
+ log_unit_info(UNIT(s),
+ "Service RestartSec=%s expired, scheduling restart.",
+ format_timespan(buf_restart, sizeof buf_restart, s->restart_usec, USEC_PER_SEC));
+ } else
+ log_unit_info(UNIT(s),
+ "Service has no hold-off time (RestartSec=0), scheduling restart.");
+
service_enter_restart(s);
break;
diff --git a/src/core/service.h b/src/core/service.h
index 5c5b24e3ef..9c06e91883 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Service Service;
typedef struct ServiceFDStore ServiceFDStore;
@@ -27,6 +8,8 @@ typedef struct ServiceFDStore ServiceFDStore;
#include "kill.h"
#include "path.h"
#include "ratelimit.h"
+#include "socket.h"
+#include "unit.h"
typedef enum ServiceRestart {
SERVICE_RESTART_NO,
@@ -183,7 +166,7 @@ struct Service {
NotifyState notify_state;
ServiceFDStore *fd_store;
- unsigned n_fd_store;
+ size_t n_fd_store;
unsigned n_fd_store_max;
unsigned n_keep_fd_store;
@@ -217,3 +200,5 @@ NotifyState notify_state_from_string(const char *s) _pure_;
const char* service_result_to_string(ServiceResult i) _const_;
ServiceResult service_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(SERVICE, Service);
diff --git a/src/core/show-status.c b/src/core/show-status.c
index 40658a2e16..63262cc716 100644
--- a/src/core/show-status.c
+++ b/src/core/show-status.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "fd-util.h"
diff --git a/src/core/show-status.h b/src/core/show-status.h
index a13d52484c..1a80de33d9 100644
--- a/src/core/show-status.h
+++ b/src/core/show-status.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "macro.h"
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index fec9c276fc..038345b752 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 ProFUSION embedded systems
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 ProFUSION embedded systems
***/
#include <errno.h>
@@ -52,8 +37,6 @@
#include "virt.h"
#include "watchdog.h"
-#define FINALIZE_ATTEMPTS 50
-
#define SYNC_PROGRESS_ATTEMPTS 3
#define SYNC_TIMEOUT_USEC (10*USEC_PER_SEC)
@@ -272,7 +255,6 @@ int main(int argc, char *argv[]) {
bool in_container, use_watchdog = false, can_initrd;
_cleanup_free_ char *cgroup = NULL;
char *arguments[3];
- unsigned retries;
int cmd, r, umount_log_level = LOG_INFO;
static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL};
char *watchdog_device;
@@ -318,7 +300,7 @@ int main(int argc, char *argv[]) {
(void) cg_get_root_path(&cgroup);
in_container = detect_container() > 0;
- use_watchdog = !!getenv("WATCHDOG_USEC");
+ use_watchdog = getenv("WATCHDOG_USEC");
watchdog_device = getenv("WATCHDOG_DEVICE");
if (watchdog_device) {
r = watchdog_set_device(watchdog_device);
@@ -352,7 +334,7 @@ int main(int argc, char *argv[]) {
can_initrd = !in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0;
/* Unmount all mountpoints, swaps, and loopback devices */
- for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
+ for (;;) {
bool changed = false;
if (use_watchdog)
@@ -414,10 +396,9 @@ int main(int argc, char *argv[]) {
}
if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
- if (retries > 0)
- log_info("All filesystems, swaps, loop devices, DM devices detached.");
+ log_info("All filesystems, swaps, loop devices and DM devices detached.");
/* Yay, done */
- goto initrd_jump;
+ break;
}
if (!changed && umount_log_level == LOG_INFO && !can_initrd) {
@@ -438,21 +419,16 @@ int main(int argc, char *argv[]) {
need_swapoff ? " swap devices," : "",
need_loop_detach ? " loop devices," : "",
need_dm_detach ? " DM devices," : "");
- goto initrd_jump;
+ break;
}
- log_debug("After %u retries, couldn't finalize remaining %s%s%s%s trying again.",
- retries + 1,
+ log_debug("Couldn't finalize remaining %s%s%s%s trying again.",
need_umount ? " file systems," : "",
need_swapoff ? " swap devices," : "",
need_loop_detach ? " loop devices," : "",
need_dm_detach ? " DM devices," : "");
}
- log_error("Too many iterations, giving up.");
-
- initrd_jump:
-
/* We're done with the watchdog. */
watchdog_free_device();
diff --git a/src/core/slice.c b/src/core/slice.c
index 1c4574b8bb..58f18a4dad 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
@@ -55,7 +37,7 @@ static void slice_set_state(Slice *t, SliceState state) {
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);
+ unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
}
static int slice_add_parent_slice(Slice *s) {
@@ -110,7 +92,7 @@ static int slice_verify(Slice *s) {
if (!slice_name_is_valid(UNIT(s)->id)) {
log_unit_error(UNIT(s), "Slice name %s is not valid. Refusing.", UNIT(s)->id);
- return -EINVAL;
+ return -ENOEXEC;
}
r = slice_build_parent_slice(UNIT(s)->id, &parent);
@@ -119,7 +101,7 @@ static int slice_verify(Slice *s) {
if (parent ? !unit_has_name(UNIT_DEREF(UNIT(s)->slice), parent) : UNIT_ISSET(UNIT(s)->slice)) {
log_unit_error(UNIT(s), "Located outside of parent slice. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
return 0;
@@ -339,7 +321,7 @@ static int slice_make_perpetual(Manager *m, const char *name, Unit **ret) {
return 0;
}
-static void slice_enumerate(Manager *m) {
+static void slice_enumerate_perpetual(Manager *m) {
Unit *u;
int r;
@@ -396,7 +378,7 @@ const UnitVTable slice_vtable = {
.bus_set_property = bus_slice_set_property,
.bus_commit_properties = bus_slice_commit_properties,
- .enumerate = slice_enumerate,
+ .enumerate_perpetual = slice_enumerate_perpetual,
.status_message_formats = {
.finished_start_job = {
diff --git a/src/core/slice.h b/src/core/slice.h
index 418327e933..4678c085c3 100644
--- a/src/core/slice.h
+++ b/src/core/slice.h
@@ -1,24 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "unit.h"
typedef struct Slice Slice;
@@ -31,3 +14,5 @@ struct Slice {
};
extern const UnitVTable slice_vtable;
+
+DEFINE_CAST(SLICE, Slice);
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index b0d3612d69..50115c0454 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -1,23 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation
+ Copyright © 2013 Intel Corporation
Authors:
Nathaniel Chen <nathaniel.chen@intel.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <dirent.h>
diff --git a/src/core/smack-setup.h b/src/core/smack-setup.h
index 8c2de5fdc5..b65daafcd8 100644
--- a/src/core/smack-setup.h
+++ b/src/core/smack-setup.h
@@ -2,24 +2,9 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation
+ Copyright © 2013 Intel Corporation
Authors:
Nathaniel Chen <nathaniel.chen@intel.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
int mac_smack_setup(bool *loaded_policy);
diff --git a/src/core/socket.c b/src/core/socket.c
index 41988788b8..56d32225c4 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <errno.h>
@@ -454,32 +436,32 @@ static int socket_verify(Socket *s) {
if (!s->ports) {
log_unit_error(UNIT(s), "Unit has no Listen setting (ListenStream=, ListenDatagram=, ListenFIFO=, ...). Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->accept && have_non_accept_socket(s)) {
log_unit_error(UNIT(s), "Unit configured for accepting sockets, but sockets are non-accepting. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->accept && s->max_connections <= 0) {
log_unit_error(UNIT(s), "MaxConnection= setting too small. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->accept && UNIT_DEREF(s->service)) {
log_unit_error(UNIT(s), "Explicit service configuration for accepting socket units not supported. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (!strv_isempty(s->symlinks) && !socket_find_symlink_target(s)) {
log_unit_error(UNIT(s), "Unit has symlinks set but none or more than one node in the file system. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
return 0;
@@ -629,8 +611,7 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
remote->socket = s;
- *p = remote;
- remote = NULL;
+ *p = TAKE_PTR(remote);
return 1;
}
@@ -800,27 +781,28 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
"%sKeepAliveTimeSec: %s\n",
prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_time, USEC_PER_SEC));
- if (s->keep_alive_interval)
+ if (s->keep_alive_interval > 0)
fprintf(f,
"%sKeepAliveIntervalSec: %s\n",
prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_interval, USEC_PER_SEC));
- if (s->keep_alive_cnt)
+ if (s->keep_alive_cnt > 0)
fprintf(f,
"%sKeepAliveProbes: %u\n",
prefix, s->keep_alive_cnt);
- if (s->defer_accept)
+ if (s->defer_accept > 0)
fprintf(f,
"%sDeferAcceptSec: %s\n",
prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->defer_accept, USEC_PER_SEC));
LIST_FOREACH(port, p, s->ports) {
- if (p->type == SOCKET_SOCKET) {
+ switch (p->type) {
+ case SOCKET_SOCKET: {
+ _cleanup_free_ char *k = NULL;
const char *t;
int r;
- char *k = NULL;
r = socket_address_print(&p->address, &k);
if (r < 0)
@@ -829,15 +811,20 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
t = k;
fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t);
- free(k);
- } else if (p->type == SOCKET_SPECIAL)
+ break;
+ }
+ case SOCKET_SPECIAL:
fprintf(f, "%sListenSpecial: %s\n", prefix, p->path);
- else if (p->type == SOCKET_USB_FUNCTION)
+ break;
+ case SOCKET_USB_FUNCTION:
fprintf(f, "%sListenUSBFunction: %s\n", prefix, p->path);
- else if (p->type == SOCKET_MQUEUE)
+ break;
+ case SOCKET_MQUEUE:
fprintf(f, "%sListenMessageQueue: %s\n", prefix, p->path);
- else
+ break;
+ default:
fprintf(f, "%sListenFIFO: %s\n", prefix, p->path);
+ }
}
fprintf(f,
@@ -1047,43 +1034,43 @@ static void socket_apply_socket_options(Socket *s, int fd) {
assert(fd >= 0);
if (s->keep_alive) {
- int b = s->keep_alive;
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &b, sizeof(b)) < 0)
+ int one = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)) < 0)
log_unit_warning_errno(UNIT(s), errno, "SO_KEEPALIVE failed: %m");
}
- if (s->keep_alive_time) {
+ if (s->keep_alive_time > 0) {
int value = s->keep_alive_time / USEC_PER_SEC;
if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPIDLE failed: %m");
}
- if (s->keep_alive_interval) {
+ if (s->keep_alive_interval > 0) {
int value = s->keep_alive_interval / USEC_PER_SEC;
if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPINTVL failed: %m");
}
- if (s->keep_alive_cnt) {
+ if (s->keep_alive_cnt > 0) {
int value = s->keep_alive_cnt;
if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPCNT failed: %m");
}
- if (s->defer_accept) {
+ if (s->defer_accept > 0) {
int value = s->defer_accept / USEC_PER_SEC;
if (setsockopt(fd, SOL_TCP, TCP_DEFER_ACCEPT, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_DEFER_ACCEPT failed: %m");
}
if (s->no_delay) {
- int b = s->no_delay;
+ int one = 1;
if (s->socket_protocol == IPPROTO_SCTP) {
- if (setsockopt(fd, SOL_SCTP, SCTP_NODELAY, &b, sizeof(b)) < 0)
+ if (setsockopt(fd, SOL_SCTP, SCTP_NODELAY, &one, sizeof(one)) < 0)
log_unit_warning_errno(UNIT(s), errno, "SCTP_NODELAY failed: %m");
} else {
- if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &b, sizeof(b)) < 0)
+ if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_NODELAY failed: %m");
}
}
@@ -1114,7 +1101,6 @@ static void socket_apply_socket_options(Socket *s, int fd) {
int value = (int) s->receive_buffer;
/* We first try with SO_RCVBUFFORCE, in case we have the perms for that */
-
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
log_unit_warning_errno(UNIT(s), errno, "SO_RCVBUF failed: %m");
@@ -1204,7 +1190,7 @@ static int fifo_address_create(
return r;
/* Enforce the right access mode for the fifo */
- old_mask = umask(~ socket_mode);
+ old_mask = umask(~socket_mode);
/* Include the original umask in our mask */
(void) umask(~socket_mode | old_mask);
@@ -1238,10 +1224,7 @@ static int fifo_address_create(
goto fail;
}
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
fail:
mac_selinux_create_file_clear();
@@ -1251,7 +1234,6 @@ fail:
static int special_address_create(const char *path, bool writable) {
_cleanup_close_ int fd = -1;
struct stat st;
- int r;
assert(path);
@@ -1266,16 +1248,12 @@ static int special_address_create(const char *path, bool writable) {
if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode))
return -EEXIST;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
static int usbffs_address_create(const char *path) {
_cleanup_close_ int fd = -1;
struct stat st;
- int r;
assert(path);
@@ -1290,10 +1268,7 @@ static int usbffs_address_create(const char *path) {
if (!S_ISREG(st.st_mode))
return -EEXIST;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
static int mq_address_create(
@@ -1306,7 +1281,6 @@ static int mq_address_create(
struct stat st;
mode_t old_mask;
struct mq_attr _attr, *attr = NULL;
- int r;
assert(path);
@@ -1320,7 +1294,7 @@ static int mq_address_create(
}
/* Enforce the right access mode for the mq */
- old_mask = umask(~ mq_mode);
+ old_mask = umask(~mq_mode);
/* Include the original umask in our mask */
(void) umask(~mq_mode | old_mask);
@@ -1338,10 +1312,7 @@ static int mq_address_create(
st.st_gid != getgid())
return -EEXIST;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
static int socket_symlink(Socket *s) {
@@ -1395,13 +1366,14 @@ static int usbffs_select_ep(const struct dirent *d) {
static int usbffs_dispatch_eps(SocketPort *p) {
_cleanup_free_ struct dirent **ent = NULL;
- int r, i, n, k;
+ size_t n, k, i;
+ int r;
r = scandir(p->path, &ent, usbffs_select_ep, alphasort);
if (r < 0)
return -errno;
- n = r;
+ n = (size_t) r;
p->auxiliary_fds = new(int, n);
if (!p->auxiliary_fds)
return -ENOMEM;
@@ -1416,15 +1388,13 @@ static int usbffs_dispatch_eps(SocketPort *p) {
if (!ep)
return -ENOMEM;
- path_kill_slashes(ep);
+ path_simplify(ep, false);
r = usbffs_address_create(ep);
if (r < 0)
goto fail;
- p->auxiliary_fds[k] = r;
-
- ++k;
+ p->auxiliary_fds[k++] = r;
free(ent[i]);
}
@@ -1439,7 +1409,9 @@ fail:
}
static int socket_determine_selinux_label(Socket *s, char **ret) {
+ Service *service;
ExecCommand *c;
+ _cleanup_free_ char *path = NULL;
int r;
assert(s);
@@ -1461,11 +1433,16 @@ static int socket_determine_selinux_label(Socket *s, char **ret) {
if (!UNIT_ISSET(s->service))
goto no_label;
- c = SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START];
+ service = SERVICE(UNIT_DEREF(s->service));
+ c = service->exec_command[SERVICE_EXEC_START];
if (!c)
goto no_label;
- r = mac_selinux_get_create_label_from_exe(c->path, ret);
+ r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path);
+ if (r < 0)
+ goto no_label;
+
+ r = mac_selinux_get_create_label_from_exe(path, ret);
if (IN_SET(r, -EPERM, -EOPNOTSUPP))
goto no_label;
}
@@ -1813,7 +1790,7 @@ static void socket_set_state(Socket *s, SocketState state) {
if (state != old_state)
log_unit_debug(UNIT(s), "Changed %s -> %s", socket_state_to_string(old_state), socket_state_to_string(state));
- unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
+ unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
}
static int socket_coldplug(Unit *u) {
@@ -2261,18 +2238,17 @@ static void socket_enter_running(Socket *s, int cfd) {
log_unit_debug(UNIT(s), "Suppressing connection request since unit stop is scheduled.");
if (cfd >= 0)
- cfd = safe_close(cfd);
+ goto refuse;
else
flush_ports(s);
return;
}
- if (!ratelimit_test(&s->trigger_limit)) {
- safe_close(cfd);
+ if (!ratelimit_below(&s->trigger_limit)) {
log_unit_warning(UNIT(s), "Trigger limit hit, refusing further activation.");
socket_enter_stop_pre(s, SOCKET_FAILURE_TRIGGER_LIMIT_HIT);
- return;
+ goto refuse;
}
if (cfd < 0) {
@@ -2310,15 +2286,13 @@ static void socket_enter_running(Socket *s, int cfd) {
if (s->n_connections >= s->max_connections) {
log_unit_warning(UNIT(s), "Too many incoming connections (%u), dropping connection.",
s->n_connections);
- safe_close(cfd);
- return;
+ goto refuse;
}
if (s->max_connections_per_source > 0) {
r = socket_acquire_peer(s, cfd, &p);
if (r < 0) {
- safe_close(cfd);
- return;
+ goto refuse;
} else if (r > 0 && p->n_ref > s->max_connections_per_source) {
_cleanup_free_ char *t = NULL;
@@ -2327,8 +2301,7 @@ static void socket_enter_running(Socket *s, int cfd) {
log_unit_warning(UNIT(s),
"Too many incoming connections (%u) from source %s, dropping connection.",
p->n_ref, strnull(t));
- safe_close(cfd);
- return;
+ goto refuse;
}
}
@@ -2344,8 +2317,7 @@ static void socket_enter_running(Socket *s, int cfd) {
/* ENOTCONN is legitimate if TCP RST was received.
* This connection is over, but the socket unit lives on. */
log_unit_debug(UNIT(s), "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring.");
- safe_close(cfd);
- return;
+ goto refuse;
}
r = unit_name_to_prefix(UNIT(s)->id, &prefix);
@@ -2373,8 +2345,7 @@ static void socket_enter_running(Socket *s, int cfd) {
cfd = -1; /* We passed ownership of the fd to the service now. Forget it here. */
s->n_connections++;
- service->peer = p; /* Pass ownership of the peer reference */
- p = NULL;
+ service->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL);
if (r < 0) {
@@ -2390,6 +2361,11 @@ static void socket_enter_running(Socket *s, int cfd) {
return;
+refuse:
+ s->n_refused++;
+ safe_close(cfd);
+ return;
+
fail:
log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",
cfd >= 0 ? "template" : "non-template",
@@ -2533,6 +2509,7 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
unit_serialize_item(u, f, "state", socket_state_to_string(s->state));
unit_serialize_item(u, f, "result", socket_result_to_string(s->result));
unit_serialize_item_format(u, f, "n-accepted", "%u", s->n_accepted);
+ unit_serialize_item_format(u, f, "n-refused", "%u", s->n_refused);
if (s->control_pid > 0)
unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
@@ -2613,6 +2590,13 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
log_unit_debug(u, "Failed to parse n-accepted value: %s", value);
else
s->n_accepted += k;
+ } else if (streq(key, "n-refused")) {
+ unsigned k;
+
+ if (safe_atou(value, &k) < 0)
+ log_unit_debug(u, "Failed to parse n-refused value: %s", value);
+ else
+ s->n_refused += k;
} else if (streq(key, "control-pid")) {
pid_t pid;
@@ -3120,8 +3104,9 @@ static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *use
}
int socket_collect_fds(Socket *s, int **fds) {
- int *rfds, k = 0, n = 0;
+ size_t k = 0, n = 0;
SocketPort *p;
+ int *rfds;
assert(s);
assert(fds);
@@ -3144,7 +3129,7 @@ int socket_collect_fds(Socket *s, int **fds) {
return -ENOMEM;
LIST_FOREACH(port, p, s->ports) {
- int i;
+ size_t i;
if (p->fd >= 0)
rfds[k++] = p->fd;
@@ -3155,7 +3140,7 @@ int socket_collect_fds(Socket *s, int **fds) {
assert(k == n);
*fds = rfds;
- return n;
+ return (int) n;
}
static void socket_reset_failed(Unit *u) {
diff --git a/src/core/socket.h b/src/core/socket.h
index 84ec9cff08..c4e25db1fc 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -1,31 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Socket Socket;
typedef struct SocketPeer SocketPeer;
#include "mount.h"
#include "service.h"
#include "socket-util.h"
+#include "unit.h"
typedef enum SocketExecCommand {
SOCKET_EXEC_START_PRE,
@@ -67,7 +49,7 @@ typedef struct SocketPort {
SocketType type;
int fd;
int *auxiliary_fds;
- int n_auxiliary_fds;
+ size_t n_auxiliary_fds;
SocketAddress address;
char *path;
@@ -85,6 +67,7 @@ struct Socket {
unsigned n_accepted;
unsigned n_connections;
+ unsigned n_refused;
unsigned max_connections;
unsigned max_connections_per_source;
@@ -195,3 +178,5 @@ SocketResult socket_result_from_string(const char *s) _pure_;
const char* socket_port_type_to_string(SocketPort *p) _pure_;
SocketType socket_port_type_from_string(const char *p) _pure_;
+
+DEFINE_CAST(SOCKET, Socket);
diff --git a/src/core/swap.c b/src/core/swap.c
index ed397c4c9e..b78b1aa266 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <sys/epoll.h>
@@ -27,6 +9,7 @@
#include "alloc-util.h"
#include "dbus-swap.h"
+#include "device.h"
#include "escape.h"
#include "exit-status.h"
#include "fd-util.h"
@@ -252,30 +235,34 @@ static int swap_verify(Swap *s) {
if (!unit_has_name(UNIT(s), e)) {
log_unit_error(UNIT(s), "Value of What= and unit name do not match, not loading.");
- return -EINVAL;
+ return -ENOEXEC;
}
if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load.");
- return -EINVAL;
+ return -ENOEXEC;
}
return 0;
}
static int swap_load_devnode(Swap *s) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
struct stat st;
const char *p;
+ int r;
assert(s);
if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode))
return 0;
- d = udev_device_new_from_devnum(UNIT(s)->manager->udev, 'b', st.st_rdev);
- if (!d)
+ r = udev_device_new_from_stat_rdev(UNIT(s)->manager->udev, &st, &d);
+ if (r < 0) {
+ log_unit_full(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to allocate udev device for swap %s: %m", s->what);
return 0;
+ }
p = udev_device_get_devnode(d);
if (!p)
@@ -319,7 +306,7 @@ static int swap_load(Unit *u) {
return -ENOMEM;
}
- path_kill_slashes(s->what);
+ path_simplify(s->what, false);
if (!UNIT(s)->description) {
r = unit_set_description(u, s->what);
@@ -438,7 +425,7 @@ fail:
}
static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
const char *dn;
struct stat st;
@@ -455,9 +442,12 @@ static int swap_process_new(Manager *m, const char *device, int prio, bool set_f
if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
return 0;
- d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev);
- if (!d)
+ r = udev_device_new_from_stat_rdev(m->udev, &st, &d);
+ if (r < 0) {
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to allocate udev device for swap %s: %m", device);
return 0;
+ }
/* Add the main device node */
dn = udev_device_get_devnode(d);
@@ -508,7 +498,7 @@ static void swap_set_state(Swap *s, SwapState state) {
if (state != old_state)
log_unit_debug(UNIT(s), "Changed %s -> %s", swap_state_to_string(old_state), swap_state_to_string(state));
- unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
+ unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
/* If there other units for the same device node have a job
queued it might be worth checking again if it is runnable
@@ -1124,7 +1114,7 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
if (cunescape(dev, UNESCAPE_RELAX, &d) < 0)
return log_oom();
- device_found_node(m, d, true, DEVICE_FOUND_SWAP, set_flags);
+ device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP);
k = swap_process_new(m, d, prio, set_flags);
if (k < 0)
@@ -1179,7 +1169,7 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
}
if (swap->what)
- device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true);
+ device_found_node(m, swap->what, 0, DEVICE_FOUND_SWAP);
} else if (swap->just_activated) {
@@ -1253,7 +1243,7 @@ static Unit *swap_following(Unit *u) {
static int swap_following_set(Unit *u, Set **_set) {
Swap *s = SWAP(u), *other;
- Set *set;
+ _cleanup_set_free_ Set *set = NULL;
int r;
assert(s);
@@ -1271,24 +1261,18 @@ static int swap_following_set(Unit *u, Set **_set) {
LIST_FOREACH_OTHERS(same_devnode, other, s) {
r = set_put(set, other);
if (r < 0)
- goto fail;
+ return r;
}
- *_set = set;
+ *_set = TAKE_PTR(set);
return 1;
-
-fail:
- set_free(set);
- return r;
}
static void swap_shutdown(Manager *m) {
assert(m);
m->swap_event_source = sd_event_source_unref(m->swap_event_source);
-
m->proc_swaps = safe_fclose(m->proc_swaps);
-
m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode);
}
@@ -1301,9 +1285,9 @@ static void swap_enumerate(Manager *m) {
m->proc_swaps = fopen("/proc/swaps", "re");
if (!m->proc_swaps) {
if (errno == ENOENT)
- log_debug("Not swap enabled, skipping enumeration");
+ log_debug_errno(errno, "Not swap enabled, skipping enumeration.");
else
- log_error_errno(errno, "Failed to open /proc/swaps: %m");
+ log_warning_errno(errno, "Failed to open /proc/swaps, ignoring: %m");
return;
}
diff --git a/src/core/swap.h b/src/core/swap.h
index fa9d45ac0c..1c0c7fcadc 100644
--- a/src/core/swap.h
+++ b/src/core/swap.h
@@ -2,26 +2,11 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Maarten Lankhorst
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 Maarten Lankhorst
***/
#include "libudev.h"
+#include "unit.h"
typedef struct Swap Swap;
@@ -108,3 +93,5 @@ SwapExecCommand swap_exec_command_from_string(const char *s) _pure_;
const char* swap_result_to_string(SwapResult i) _const_;
SwapResult swap_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(SWAP, Swap);
diff --git a/src/core/system.conf.in b/src/core/system.conf.in
index 08cbe529ba..f0a59a79a5 100644
--- a/src/core/system.conf.in
+++ b/src/core/system.conf.in
@@ -27,6 +27,7 @@
#RuntimeWatchdogSec=0
#ShutdownWatchdogSec=10min
#CapabilityBoundingSet=
+#NoNewPrivileges=no
#SystemCallArchitectures=
#TimerSlackNSec=
#DefaultTimerAccuracySec=1min
diff --git a/src/core/target.c b/src/core/target.c
index 756cbbfb6c..6446767504 100644
--- a/src/core/target.c
+++ b/src/core/target.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "dbus-target.h"
#include "log.h"
@@ -44,7 +26,7 @@ static void target_set_state(Target *t, TargetState state) {
target_state_to_string(old_state),
target_state_to_string(state));
- unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
+ unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
}
static int target_add_default_dependencies(Target *t) {
diff --git a/src/core/target.h b/src/core/target.h
index 8d44a11545..28f78888dc 100644
--- a/src/core/target.h
+++ b/src/core/target.h
@@ -1,24 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "unit.h"
typedef struct Target Target;
@@ -29,3 +12,5 @@ struct Target {
};
extern const UnitVTable target_vtable;
+
+DEFINE_CAST(TARGET, Target);
diff --git a/src/core/timer.c b/src/core/timer.c
index ddb9c82b87..db202971d3 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
@@ -91,7 +73,7 @@ static int timer_verify(Timer *t) {
if (!t->values) {
log_unit_error(UNIT(t), "Timer unit lacks value setting. Refusing.");
- return -EINVAL;
+ return -ENOEXEC;
}
return 0;
@@ -277,7 +259,7 @@ static void timer_set_state(Timer *t, TimerState state) {
if (state != old_state)
log_unit_debug(UNIT(t), "Changed %s -> %s", timer_state_to_string(old_state), timer_state_to_string(state));
- unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
+ unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
}
static void timer_enter_waiting(Timer *t, bool initial);
@@ -832,6 +814,18 @@ static void timer_time_change(Unit *u) {
timer_enter_waiting(t, false);
}
+static void timer_timezone_change(Unit *u) {
+ Timer *t = TIMER(u);
+
+ assert(u);
+
+ if (t->state != TIMER_WAITING)
+ return;
+
+ log_unit_debug(u, "Timezone change, recalculating next elapse.");
+ timer_enter_waiting(t, false);
+}
+
static const char* const timer_base_table[_TIMER_BASE_MAX] = {
[TIMER_ACTIVE] = "OnActiveSec",
[TIMER_BOOT] = "OnBootSec",
@@ -881,6 +875,7 @@ const UnitVTable timer_vtable = {
.reset_failed = timer_reset_failed,
.time_change = timer_time_change,
+ .timezone_change = timer_timezone_change,
.bus_vtable = bus_timer_vtable,
.bus_set_property = bus_timer_set_property,
diff --git a/src/core/timer.h b/src/core/timer.h
index 096d48bd34..833aadb0b8 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -1,28 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Timer Timer;
#include "calendarspec.h"
+#include "unit.h"
typedef enum TimerBase {
TIMER_ACTIVE,
@@ -90,3 +72,5 @@ TimerBase timer_base_from_string(const char *s) _pure_;
const char* timer_result_to_string(TimerResult i) _const_;
TimerResult timer_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(TIMER, Timer);
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 32ad660026..1c7efb207a 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <unistd.h>
@@ -413,7 +395,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
j->unit->id,
unit_id == array ? "ordering cycle" : "dependency",
*unit_id, *job_type,
- unit_ids, NULL);
+ unit_ids);
if (delete) {
const char *status;
@@ -422,7 +404,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
"MESSAGE=%s: Job %s/%s deleted to break ordering cycle starting with %s/%s",
j->unit->id, delete->unit->id, job_type_to_string(delete->type),
j->unit->id, job_type_to_string(j->type),
- unit_ids, NULL);
+ unit_ids);
if (log_get_show_color())
status = ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL;
@@ -438,7 +420,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
log_struct(LOG_ERR,
"MESSAGE=%s: Unable to break cycle starting with %s/%s",
j->unit->id, j->unit->id, job_type_to_string(j->type),
- unit_ids, NULL);
+ unit_ids);
return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
"Transaction order is cyclic. See system logs for details.");
@@ -919,11 +901,13 @@ int transaction_add_job_and_dependencies(
/* by ? by->unit->id : "NA", */
/* by ? job_type_to_string(by->type) : "NA"); */
- if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_MASKED))
+ /* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
+ * temporarily. */
+ if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED))
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
if (type != JOB_STOP) {
- r = bus_unit_check_load_state(unit, e);
+ r = bus_unit_validate_load_state(unit, e);
if (r < 0)
return r;
}
@@ -933,7 +917,6 @@ int transaction_add_job_and_dependencies(
"Job type %s is not applicable for unit %s.",
job_type_to_string(type), unit->id);
-
/* First add the job. */
ret = transaction_add_one_job(tr, type, unit, &is_new);
if (!ret)
diff --git a/src/core/transaction.h b/src/core/transaction.h
index 0d57b27f2e..70d74a4ccb 100644
--- a/src/core/transaction.h
+++ b/src/core/transaction.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Transaction Transaction;
#include "hashmap.h"
diff --git a/src/core/triggers.systemd.in b/src/core/triggers.systemd.in
index 4ebb4e7795..10b1889b57 100644
--- a/src/core/triggers.systemd.in
+++ b/src/core/triggers.systemd.in
@@ -2,22 +2,7 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# This file is part of systemd.
-#
-# Copyright 2015 Zbigniew Jędrzejewski-Szmek
-# Copyright 2018 Neal Gompa
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+# Copyright © 2018 Neal Gompa
# The contents of this are an example to be copied into systemd.spec.
#
diff --git a/src/core/umount.c b/src/core/umount.c
index ab2d4ffa62..241fe6fc62 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 ProFUSION embedded systems
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 ProFUSION embedded systems
***/
#include <errno.h>
@@ -25,6 +10,9 @@
#include <sys/mount.h>
#include <sys/swap.h>
+/* This needs to be after sys/mount.h :( */
+#include <libmount.h>
+
#include "libudev.h"
#include "alloc-util.h"
@@ -34,7 +22,6 @@
#include "fd-util.h"
#include "fstab-util.h"
#include "linux-3.13/dm-ioctl.h"
-#include "list.h"
#include "mount-setup.h"
#include "mount-util.h"
#include "path-util.h"
@@ -46,14 +33,8 @@
#include "util.h"
#include "virt.h"
-typedef struct MountPoint {
- char *path;
- char *remount_options;
- unsigned long remount_flags;
- bool try_remount_ro;
- dev_t devnum;
- LIST_FIELDS(struct MountPoint, mount_point);
-} MountPoint;
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
static void mount_point_free(MountPoint **head, MountPoint *m) {
assert(head);
@@ -66,54 +47,53 @@ static void mount_point_free(MountPoint **head, MountPoint *m) {
free(m);
}
-static void mount_points_list_free(MountPoint **head) {
+void mount_points_list_free(MountPoint **head) {
assert(head);
while (*head)
mount_point_free(head, *head);
}
-static int mount_points_list_get(MountPoint **head) {
- _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
- unsigned int i;
+int mount_points_list_get(const char *mountinfo, MountPoint **head) {
+ _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
+ _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
int r;
assert(head);
- proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
- if (!proc_self_mountinfo)
- return -errno;
+ t = mnt_new_table();
+ i = mnt_new_iter(MNT_ITER_FORWARD);
+ if (!t || !i)
+ return log_oom();
- for (i = 1;; i++) {
- _cleanup_free_ char *path = NULL, *options = NULL, *flags = NULL, *type = NULL, *p = NULL;
+ r = mnt_table_parse_mtab(t, mountinfo);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse %s: %m", mountinfo);
+
+ for (;;) {
+ struct libmnt_fs *fs;
+ const char *path, *options, *fstype;
+ _cleanup_free_ char *p = NULL;
+ unsigned long remount_flags = 0u;
+ _cleanup_free_ char *remount_options = NULL;
+ bool try_remount_ro;
MountPoint *m;
- int k;
-
- k = fscanf(proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%ms" /* (6) mount flags */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%ms " /* (9) file system type */
- "%*s" /* (10) mount source */
- "%ms" /* (11) mount options */
- "%*[^\n]", /* some rubbish at the end */
- &path, &flags, &type, &options);
- if (k != 4) {
- if (k == EOF)
- break;
-
- log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
- continue;
- }
- r = cunescape(path, UNESCAPE_RELAX, &p);
+ r = mnt_table_next_fs(t, i, &fs);
+ if (r == 1)
+ break;
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to get next entry from %s: %m", mountinfo);
+
+ path = mnt_fs_get_target(fs);
+ if (!path)
+ continue;
+
+ if (cunescape(path, UNESCAPE_RELAX, &p) < 0)
+ return log_oom();
+
+ options = mnt_fs_get_options(fs);
+ fstype = mnt_fs_get_fstype(fs);
/* Ignore mount points we can't unmount because they
* are API or because we are keeping them open (like
@@ -129,12 +109,6 @@ static int mount_points_list_get(MountPoint **head) {
path_startswith(p, "/proc"))
continue;
- m = new0(MountPoint, 1);
- if (!m)
- return -ENOMEM;
-
- free_and_replace(m->path, p);
-
/* If we are in a container, don't attempt to
* read-only mount anything as that brings no real
* benefits, but might confuse the host, as we remount
@@ -145,79 +119,84 @@ static int mount_points_list_get(MountPoint **head) {
* a "dirty fs") and could hang if the network is down.
* Note that umount2() is more careful and will not
* hang because of the network being down. */
- m->try_remount_ro = detect_container() <= 0 &&
- !fstype_is_network(type) &&
- !fstype_is_api_vfs(type) &&
- !fstype_is_ro(type) &&
- !fstab_test_yes_no_option(options, "ro\0rw\0");
-
- if (m->try_remount_ro) {
- _cleanup_free_ char *unknown_flags = NULL;
+ try_remount_ro = detect_container() <= 0 &&
+ !fstype_is_network(fstype) &&
+ !fstype_is_api_vfs(fstype) &&
+ !fstype_is_ro(fstype) &&
+ !fstab_test_yes_no_option(options, "ro\0rw\0");
+ if (try_remount_ro) {
/* mount(2) states that mount flags and options need to be exactly the same
* as they were when the filesystem was mounted, except for the desired
* changes. So we reconstruct both here and adjust them for the later
* remount call too. */
- r = mount_option_mangle(flags, 0, &m->remount_flags, &unknown_flags);
- if (r < 0)
- return r;
- if (!isempty(unknown_flags))
- log_warning("Ignoring unknown mount flags '%s'.", unknown_flags);
+ r = mnt_fs_get_propagation(fs, &remount_flags);
+ if (r < 0) {
+ log_warning_errno(r, "mnt_fs_get_propagation() failed for %s, ignoring: %m", path);
+ continue;
+ }
- r = mount_option_mangle(options, m->remount_flags, &m->remount_flags, &m->remount_options);
- if (r < 0)
- return r;
+ r = mount_option_mangle(options, remount_flags, &remount_flags, &remount_options);
+ if (r < 0) {
+ log_warning_errno(r, "mount_option_mangle failed for %s, ignoring: %m", path);
+ continue;
+ }
/* MS_BIND is special. If it is provided it will only make the mount-point
* read-only. If left out, the super block itself is remounted, which we want. */
- m->remount_flags = (m->remount_flags|MS_REMOUNT|MS_RDONLY) & ~MS_BIND;
+ remount_flags = (remount_flags|MS_REMOUNT|MS_RDONLY) & ~MS_BIND;
}
+ m = new0(MountPoint, 1);
+ if (!m)
+ return log_oom();
+
+ free_and_replace(m->path, p);
+ free_and_replace(m->remount_options, remount_options);
+ m->remount_flags = remount_flags;
+ m->try_remount_ro = try_remount_ro;
+
LIST_PREPEND(mount_point, *head, m);
}
return 0;
}
-static int swap_list_get(MountPoint **head) {
- _cleanup_fclose_ FILE *proc_swaps = NULL;
- unsigned int i;
+int swap_list_get(const char *swaps, MountPoint **head) {
+ _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
+ _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
int r;
assert(head);
- proc_swaps = fopen("/proc/swaps", "re");
- if (!proc_swaps)
- return (errno == ENOENT) ? 0 : -errno;
+ t = mnt_new_table();
+ i = mnt_new_iter(MNT_ITER_FORWARD);
+ if (!t || !i)
+ return log_oom();
- (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n");
+ r = mnt_table_parse_swaps(t, swaps);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse %s: %m", swaps);
+
+ for (;;) {
+ struct libmnt_fs *fs;
- for (i = 2;; i++) {
MountPoint *swap;
- _cleanup_free_ char *dev = NULL, *d = NULL;
- int k;
-
- k = fscanf(proc_swaps,
- "%ms " /* device/file */
- "%*s " /* type of swap */
- "%*s " /* swap size */
- "%*s " /* used */
- "%*s\n", /* priority */
- &dev);
-
- if (k != 1) {
- if (k == EOF)
- break;
-
- log_warning("Failed to parse /proc/swaps:%u.", i);
- continue;
- }
+ const char *source;
+ _cleanup_free_ char *d = NULL;
- if (endswith(dev, " (deleted)"))
+ r = mnt_table_next_fs(t, i, &fs);
+ if (r == 1)
+ break;
+ if (r < 0)
+ return log_error_errno(r, "Failed to get next entry from %s: %m", swaps);
+
+ source = mnt_fs_get_source(fs);
+ if (!source)
continue;
- r = cunescape(dev, UNESCAPE_RELAX, &d);
+ r = cunescape(source, UNESCAPE_RELAX, &d);
if (r < 0)
return r;
@@ -233,9 +212,9 @@ static int swap_list_get(MountPoint **head) {
}
static int loopback_list_get(MountPoint **head) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
int r;
assert(head);
@@ -266,10 +245,9 @@ static int loopback_list_get(MountPoint **head) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- MountPoint *lb;
- _cleanup_udev_device_unref_ struct udev_device *d;
- char *loop;
+ _cleanup_(udev_device_unrefp) struct udev_device *d;
const char *dn;
+ _cleanup_free_ MountPoint *lb = NULL;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
if (!d)
@@ -279,27 +257,25 @@ static int loopback_list_get(MountPoint **head) {
if (!dn)
continue;
- loop = strdup(dn);
- if (!loop)
- return -ENOMEM;
-
lb = new0(MountPoint, 1);
- if (!lb) {
- free(loop);
+ if (!lb)
return -ENOMEM;
- }
- lb->path = loop;
+ r = free_and_strdup(&lb->path, dn);
+ if (r < 0)
+ return r;
+
LIST_PREPEND(mount_point, *head, lb);
+ lb = NULL;
}
return 0;
}
static int dm_list_get(MountPoint **head) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
int r;
assert(head);
@@ -326,11 +302,10 @@ static int dm_list_get(MountPoint **head) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- MountPoint *m;
- _cleanup_udev_device_unref_ struct udev_device *d;
+ _cleanup_(udev_device_unrefp) struct udev_device *d;
dev_t devnum;
- char *node;
const char *dn;
+ _cleanup_free_ MountPoint *m = NULL;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
if (!d)
@@ -341,19 +316,17 @@ static int dm_list_get(MountPoint **head) {
if (major(devnum) == 0 || !dn)
continue;
- node = strdup(dn);
- if (!node)
- return -ENOMEM;
-
m = new0(MountPoint, 1);
- if (!m) {
- free(node);
+ if (!m)
return -ENOMEM;
- }
- m->path = node;
m->devnum = devnum;
+ r = free_and_strdup(&m->path, dn);
+ if (r < 0)
+ return r;
+
LIST_PREPEND(mount_point, *head, m);
+ m = NULL;
}
return 0;
@@ -647,21 +620,16 @@ static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_lo
static int umount_all_once(bool *changed, int umount_log_level) {
int r;
- LIST_HEAD(MountPoint, mp_list_head);
+ _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
assert(changed);
LIST_HEAD_INIT(mp_list_head);
- r = mount_points_list_get(&mp_list_head);
+ r = mount_points_list_get(NULL, &mp_list_head);
if (r < 0)
- goto end;
-
- r = mount_points_list_umount(&mp_list_head, changed, umount_log_level);
-
- end:
- mount_points_list_free(&mp_list_head);
+ return r;
- return r;
+ return mount_points_list_umount(&mp_list_head, changed, umount_log_level);
}
int umount_all(bool *changed, int umount_log_level) {
@@ -685,28 +653,23 @@ int umount_all(bool *changed, int umount_log_level) {
}
int swapoff_all(bool *changed) {
+ _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, swap_list_head);
int r;
- LIST_HEAD(MountPoint, swap_list_head);
assert(changed);
LIST_HEAD_INIT(swap_list_head);
- r = swap_list_get(&swap_list_head);
+ r = swap_list_get(NULL, &swap_list_head);
if (r < 0)
- goto end;
-
- r = swap_points_list_off(&swap_list_head, changed);
-
- end:
- mount_points_list_free(&swap_list_head);
+ return r;
- return r;
+ return swap_points_list_off(&swap_list_head, changed);
}
int loopback_detach_all(bool *changed, int umount_log_level) {
+ _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, loopback_list_head);
int r;
- LIST_HEAD(MountPoint, loopback_list_head);
assert(changed);
@@ -714,19 +677,14 @@ int loopback_detach_all(bool *changed, int umount_log_level) {
r = loopback_list_get(&loopback_list_head);
if (r < 0)
- goto end;
-
- r = loopback_points_list_detach(&loopback_list_head, changed, umount_log_level);
-
- end:
- mount_points_list_free(&loopback_list_head);
+ return r;
- return r;
+ return loopback_points_list_detach(&loopback_list_head, changed, umount_log_level);
}
int dm_detach_all(bool *changed, int umount_log_level) {
+ _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, dm_list_head);
int r;
- LIST_HEAD(MountPoint, dm_list_head);
assert(changed);
@@ -734,12 +692,7 @@ int dm_detach_all(bool *changed, int umount_log_level) {
r = dm_list_get(&dm_list_head);
if (r < 0)
- goto end;
-
- r = dm_points_list_detach(&dm_list_head, changed, umount_log_level);
-
- end:
- mount_points_list_free(&dm_list_head);
+ return r;
- return r;
+ return dm_points_list_detach(&dm_list_head, changed, umount_log_level);
}
diff --git a/src/core/umount.h b/src/core/umount.h
index a6613e6ad6..6f2b24d195 100644
--- a/src/core/umount.h
+++ b/src/core/umount.h
@@ -2,24 +2,11 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 ProFUSION embedded systems
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 ProFUSION embedded systems
***/
+#include "list.h"
+
int umount_all(bool *changed, int umount_log_level);
int swapoff_all(bool *changed);
@@ -27,3 +14,17 @@ int swapoff_all(bool *changed);
int loopback_detach_all(bool *changed, int umount_log_level);
int dm_detach_all(bool *changed, int umount_log_level);
+
+/* This is exported just for testing */
+typedef struct MountPoint {
+ char *path;
+ char *remount_options;
+ unsigned long remount_flags;
+ bool try_remount_ro;
+ dev_t devnum;
+ LIST_FIELDS(struct MountPoint, mount_point);
+} MountPoint;
+
+int mount_points_list_get(const char *mountinfo, MountPoint **head);
+void mount_points_list_free(MountPoint **head);
+int swap_list_get(const char *swaps, MountPoint **head);
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index e61e0d1475..046e937e92 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "cgroup-util.h"
@@ -68,6 +50,37 @@ static int specifier_instance_unescaped(char specifier, void *data, void *userda
return unit_name_unescape(strempty(u->instance), ret);
}
+static int specifier_last_component(char specifier, void *data, void *userdata, char **ret) {
+ Unit *u = userdata;
+ _cleanup_free_ char *prefix = NULL;
+ char *dash;
+ int r;
+
+ assert(u);
+
+ r = unit_name_to_prefix(u->id, &prefix);
+ if (r < 0)
+ return r;
+
+ dash = strrchr(prefix, '-');
+ if (dash)
+ return specifier_string(specifier, dash + 1, userdata, ret);
+
+ *ret = TAKE_PTR(prefix);
+ return 0;
+}
+
+static int specifier_last_component_unescaped(char specifier, void *data, void *userdata, char **ret) {
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ r = specifier_last_component(specifier, data, userdata, &p);
+ if (r < 0)
+ return r;
+
+ return unit_name_unescape(p, ret);
+}
+
static int specifier_filename(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
@@ -214,6 +227,9 @@ int unit_full_printf(Unit *u, const char *format, char **ret) {
* %S: the state directory root (e.g. /var/lib or $XDG_CONFIG_HOME)
* %C: the cache directory root (e.g. /var/cache or $XDG_CACHE_HOME)
* %L: the log directory root (e.g. /var/log or $XDG_CONFIG_HOME/log)
+ * %E: the configuration directory root (e.g. /etc or $XDG_CONFIG_HOME)
+ * %T: the temporary directory (e.g. /tmp, or $TMPDIR, $TEMP, $TMP)
+ * %V: the temporary directory for large, persistent stuff (e.g. /var/tmp, or $TMPDIR, $TEMP, $TMP)
*
* %h: the homedir of the running user
* %s: the shell of the running user
@@ -226,31 +242,37 @@ int unit_full_printf(Unit *u, const char *format, char **ret) {
*/
const Specifier table[] = {
- { 'n', specifier_string, u->id },
- { 'N', specifier_prefix_and_instance, NULL },
- { 'p', specifier_prefix, NULL },
- { 'P', specifier_prefix_unescaped, NULL },
- { 'i', specifier_string, u->instance },
- { 'I', specifier_instance_unescaped, NULL },
-
- { 'f', specifier_filename, NULL },
- { 'c', specifier_cgroup, NULL },
- { 'r', specifier_cgroup_slice, NULL },
- { 'R', specifier_cgroup_root, NULL },
- { 't', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_RUNTIME) },
- { 'S', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_STATE) },
- { 'C', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_CACHE) },
- { 'L', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_LOGS) },
-
- { 'U', specifier_user_id, NULL },
- { 'u', specifier_user_name, NULL },
- { 'h', specifier_user_home, NULL },
- { 's', specifier_user_shell, NULL },
-
- { 'm', specifier_machine_id, NULL },
- { 'H', specifier_host_name, NULL },
- { 'b', specifier_boot_id, NULL },
- { 'v', specifier_kernel_release, NULL },
+ { 'n', specifier_string, u->id },
+ { 'N', specifier_prefix_and_instance, NULL },
+ { 'p', specifier_prefix, NULL },
+ { 'P', specifier_prefix_unescaped, NULL },
+ { 'i', specifier_string, u->instance },
+ { 'I', specifier_instance_unescaped, NULL },
+ { 'j', specifier_last_component, NULL },
+ { 'J', specifier_last_component_unescaped, NULL },
+
+ { 'f', specifier_filename, NULL },
+ { 'c', specifier_cgroup, NULL },
+ { 'r', specifier_cgroup_slice, NULL },
+ { 'R', specifier_cgroup_root, NULL },
+
+ { 't', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_RUNTIME) },
+ { 'S', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_STATE) },
+ { 'C', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_CACHE) },
+ { 'L', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_LOGS) },
+ { 'E', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_CONFIGURATION) },
+ { 'T', specifier_tmp_dir, NULL },
+ { 'V', specifier_var_tmp_dir, NULL },
+
+ { 'U', specifier_user_id, NULL },
+ { 'u', specifier_user_name, NULL },
+ { 'h', specifier_user_home, NULL },
+ { 's', specifier_user_shell, NULL },
+
+ { 'm', specifier_machine_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'b', specifier_boot_id, NULL },
+ { 'v', specifier_kernel_release, NULL },
{}
};
diff --git a/src/core/unit-printf.h b/src/core/unit-printf.h
index f1b620e162..5bd1d77bb2 100644
--- a/src/core/unit-printf.h
+++ b/src/core/unit-printf.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "unit.h"
int unit_name_printf(Unit *u, const char* text, char **ret);
diff --git a/src/core/unit.c b/src/core/unit.c
index ce15b8e088..113205bf25 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
@@ -29,6 +11,7 @@
#include "sd-messages.h"
#include "alloc-util.h"
+#include "all-units.h"
#include "bus-common-errors.h"
#include "bus-util.h"
#include "cgroup-util.h"
@@ -128,7 +111,7 @@ Unit *unit_new(Manager *m, size_t size) {
}
int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret) {
- Unit *u;
+ _cleanup_(unit_freep) Unit *u = NULL;
int r;
u = unit_new(m, size);
@@ -136,12 +119,11 @@ int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret) {
return -ENOMEM;
r = unit_add_name(u, name);
- if (r < 0) {
- unit_free(u);
+ if (r < 0)
return r;
- }
- *ret = u;
+ *ret = TAKE_PTR(u);
+
return r;
}
@@ -267,13 +249,11 @@ int unit_add_name(Unit *u, const char *text) {
if (u->type == _UNIT_TYPE_INVALID) {
u->type = t;
u->id = s;
- u->instance = i;
+ u->instance = TAKE_PTR(i);
LIST_PREPEND(units_by_type, u->manager->units_by_type[t], u);
unit_init(u);
-
- i = NULL;
}
s = NULL;
@@ -582,8 +562,9 @@ void unit_free(Unit *u) {
unit_done(u);
- sd_bus_slot_unref(u->match_bus_slot);
+ unit_dequeue_rewatch_pids(u);
+ sd_bus_slot_unref(u->match_bus_slot);
sd_bus_track_unref(u->bus_track);
u->deserialized_refs = strv_free(u->deserialized_refs);
@@ -650,6 +631,9 @@ void unit_free(Unit *u) {
if (u->in_cleanup_queue)
LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u);
+ if (u->in_target_deps_queue)
+ LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u);
+
safe_close(u->ip_accounting_ingress_map_fd);
safe_close(u->ip_accounting_egress_map_fd);
@@ -710,10 +694,8 @@ static int set_complete_move(Set **s, Set **other) {
if (*s)
return set_move(*s, *other);
- else {
- *s = *other;
- *other = NULL;
- }
+ else
+ *s = TAKE_PTR(*other);
return 0;
}
@@ -727,10 +709,8 @@ static int hashmap_complete_move(Hashmap **s, Hashmap **other) {
if (*s)
return hashmap_move(*s, *other);
- else {
- *s = *other;
- *other = NULL;
- }
+ else
+ *s = TAKE_PTR(*other);
return 0;
}
@@ -1069,7 +1049,7 @@ static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependency
if (mask == 0)
break;
- if ((mask & table[i].mask) == table[i].mask) {
+ if (FLAGS_SET(mask, table[i].mask)) {
if (*space)
fputc(' ', f);
else
@@ -1331,7 +1311,7 @@ int unit_load_fragment_and_dropin_optional(Unit *u) {
/* Same as unit_load_fragment_and_dropin(), but whether
* something can be loaded or not doesn't matter. */
- /* Load a .service file */
+ /* Load a .service/.socket/.slice/… file */
r = unit_load_fragment(u);
if (r < 0)
return r;
@@ -1343,6 +1323,18 @@ int unit_load_fragment_and_dropin_optional(Unit *u) {
return unit_load_dropin(unit_follow_merge(u));
}
+void unit_add_to_target_deps_queue(Unit *u) {
+ Manager *m = u->manager;
+
+ assert(u);
+
+ if (u->in_target_deps_queue)
+ return;
+
+ LIST_PREPEND(target_deps_queue, m->target_deps_queue, u);
+ u->in_target_deps_queue = true;
+}
+
int unit_add_default_target_dependency(Unit *u, Unit *target) {
assert(u);
assert(target);
@@ -1369,35 +1361,6 @@ int unit_add_default_target_dependency(Unit *u, Unit *target) {
return unit_add_dependency(target, UNIT_AFTER, u, true, UNIT_DEPENDENCY_DEFAULT);
}
-static int unit_add_target_dependencies(Unit *u) {
-
- static const UnitDependency deps[] = {
- UNIT_REQUIRED_BY,
- UNIT_REQUISITE_OF,
- UNIT_WANTED_BY,
- UNIT_BOUND_BY
- };
-
- unsigned k;
- int r = 0;
-
- assert(u);
-
- for (k = 0; k < ELEMENTSOF(deps); k++) {
- Unit *target;
- Iterator i;
- void *v;
-
- HASHMAP_FOREACH_KEY(v, target, u->dependencies[deps[k]], i) {
- r = unit_add_default_target_dependency(u, target);
- if (r < 0)
- return r;
- }
- }
-
- return r;
-}
-
static int unit_add_slice_dependencies(Unit *u) {
UnitDependencyMask mask;
assert(u);
@@ -1526,10 +1489,7 @@ int unit_load(Unit *u) {
}
if (u->load_state == UNIT_LOADED) {
-
- r = unit_add_target_dependencies(u);
- if (r < 0)
- goto fail;
+ unit_add_to_target_deps_queue(u);
r = unit_add_slice_dependencies(u);
if (r < 0)
@@ -1545,7 +1505,7 @@ int unit_load(Unit *u) {
if (u->on_failure_job_mode == JOB_ISOLATE && hashmap_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
log_unit_error(u, "More than one OnFailure= dependencies specified but OnFailureJobMode=isolate set. Refusing.");
- r = -EINVAL;
+ r = -ENOEXEC;
goto fail;
}
@@ -1563,14 +1523,18 @@ int unit_load(Unit *u) {
return 0;
fail:
- u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND : UNIT_ERROR;
+ /* We convert ENOEXEC errors to the UNIT_BAD_SETTING load state here. Configuration parsing code should hence
+ * return ENOEXEC to ensure units are placed in this state after loading */
+
+ u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND :
+ r == -ENOEXEC ? UNIT_BAD_SETTING :
+ UNIT_ERROR;
u->load_error = r;
+
unit_add_to_dbus_queue(u);
unit_add_to_gc_queue(u);
- log_unit_debug_errno(u, r, "Failed to load configuration: %m");
-
- return r;
+ return log_unit_debug_errno(u, r, "Failed to load configuration: %m");
}
static bool unit_condition_test_list(Unit *u, Condition *first, const char *(*to_string)(ConditionType t)) {
@@ -1716,8 +1680,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
LOG_MESSAGE("%s", buf),
LOG_UNIT_ID(u),
LOG_UNIT_INVOCATION_ID(u),
- mid,
- NULL);
+ mid);
}
void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) {
@@ -1732,7 +1695,7 @@ void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) {
int unit_start_limit_test(Unit *u) {
assert(u);
- if (ratelimit_test(&u->start_limit)) {
+ if (ratelimit_below(&u->start_limit)) {
u->start_limit_hit = false;
return 0;
}
@@ -1790,6 +1753,7 @@ static bool unit_verify_deps(Unit *u) {
* -EINVAL: Unit not loaded
* -EOPNOTSUPP: Unit type not supported
* -ENOLINK: The necessary dependencies are not fulfilled.
+ * -ESTALE: This unit has been started before and can't be started a second time
*/
int unit_start(Unit *u) {
UnitActiveState state;
@@ -1809,6 +1773,10 @@ int unit_start(Unit *u) {
if (u->load_state != UNIT_LOADED)
return -EINVAL;
+ /* Refuse starting scope units more than once */
+ if (UNIT_VTABLE(u)->once_only && dual_timestamp_is_set(&u->inactive_enter_timestamp))
+ return -ESTALE;
+
/* If the conditions failed, don't do anything at all. If we
* already are activating this call might still be useful to
* speed up activation in case there is some hold-off time,
@@ -1872,6 +1840,10 @@ bool unit_can_start(Unit *u) {
if (!unit_supported(u))
return false;
+ /* Scope units may be started only once */
+ if (UNIT_VTABLE(u)->once_only && dual_timestamp_is_set(&u->inactive_exit_timestamp))
+ return false;
+
return !!UNIT_VTABLE(u)->start;
}
@@ -1959,7 +1931,7 @@ int unit_reload(Unit *u) {
if (!UNIT_VTABLE(u)->reload) {
/* Unit doesn't have a reload function, but we need to propagate the reload anyway */
- unit_notify(u, unit_active_state(u), unit_active_state(u), true);
+ unit_notify(u, unit_active_state(u), unit_active_state(u), 0);
return 0;
}
@@ -2016,7 +1988,7 @@ static void unit_check_unneeded(Unit *u) {
/* If stopping a unit fails continuously we might enter a stop
* loop here, hence stop acting on the service being
* unnecessary after a while. */
- if (!ratelimit_test(&u->auto_stop_ratelimit)) {
+ if (!ratelimit_below(&u->auto_stop_ratelimit)) {
log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently.");
return;
}
@@ -2066,7 +2038,7 @@ static void unit_check_binds_to(Unit *u) {
/* If stopping a unit fails continuously we might enter a stop
* loop here, hence stop acting on the service being
* unnecessary after a while. */
- if (!ratelimit_test(&u->auto_stop_ratelimit)) {
+ if (!ratelimit_below(&u->auto_stop_ratelimit)) {
log_unit_warning(u, "Unit is bound to inactive unit %s, but not stopping since we tried this too often recently.", other->id);
return;
}
@@ -2153,6 +2125,7 @@ void unit_start_on_failure(Unit *u) {
Unit *other;
Iterator i;
void *v;
+ int r;
assert(u);
@@ -2162,11 +2135,11 @@ void unit_start_on_failure(Unit *u) {
log_unit_info(u, "Triggering OnFailure= dependencies.");
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_ON_FAILURE], i) {
- int r;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, NULL, NULL);
+ r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, &error, NULL);
if (r < 0)
- log_unit_error_errno(u, r, "Failed to enqueue OnFailure= job: %m");
+ log_unit_warning_errno(u, r, "Failed to enqueue OnFailure= job, ignoring: %s", bus_error_message(&error, r));
}
}
@@ -2324,10 +2297,9 @@ static void unit_update_on_console(Unit *u) {
manager_ref_console(u->manager);
else
manager_unref_console(u->manager);
-
}
-void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
+void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags) {
bool unexpected;
Manager *m;
@@ -2403,7 +2375,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
if (u->job->state == JOB_RUNNING) {
if (ns == UNIT_ACTIVE)
- job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true, false);
+ job_finish_and_invalidate(u->job, (flags & UNIT_NOTIFY_RELOAD_FAILURE) ? JOB_FAILED : JOB_DONE, true, false);
else if (!IN_SET(ns, UNIT_ACTIVATING, UNIT_RELOADING)) {
unexpected = true;
@@ -2456,7 +2428,9 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
if (ns != os && ns == UNIT_FAILED) {
log_unit_debug(u, "Unit entered failed state.");
- unit_start_on_failure(u);
+
+ if (!(flags & UNIT_NOTIFY_WILL_AUTO_RESTART))
+ unit_start_on_failure(u);
}
}
@@ -2502,10 +2476,8 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
}
}
- if (!MANAGER_IS_RELOADING(u->manager)) {
- manager_recheck_journal(m);
- manager_recheck_dbus(m);
- }
+ manager_recheck_journal(m);
+ manager_recheck_dbus(m);
unit_trigger_notify(u);
@@ -2632,7 +2604,8 @@ void unit_unwatch_all_pids(Unit *u) {
u->pids = set_free(u->pids);
}
-void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) {
+static void unit_tidy_watch_pids(Unit *u) {
+ pid_t except1, except2;
Iterator i;
void *e;
@@ -2640,6 +2613,9 @@ void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) {
/* Cleans dead PIDs from our list */
+ except1 = unit_main_pid(u);
+ except2 = unit_control_pid(u);
+
SET_FOREACH(e, u->pids, i) {
pid_t pid = PTR_TO_PID(e);
@@ -2651,6 +2627,76 @@ void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) {
}
}
+static int on_rewatch_pids_event(sd_event_source *s, void *userdata) {
+ Unit *u = userdata;
+
+ assert(s);
+ assert(u);
+
+ unit_tidy_watch_pids(u);
+ unit_watch_all_pids(u);
+
+ /* If the PID set is empty now, then let's finish this off. */
+ unit_synthesize_cgroup_empty_event(u);
+
+ return 0;
+}
+
+int unit_enqueue_rewatch_pids(Unit *u) {
+ int r;
+
+ assert(u);
+
+ if (!u->cgroup_path)
+ return -ENOENT;
+
+ r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
+ if (r < 0)
+ return r;
+ if (r > 0) /* On unified we can use proper notifications */
+ return 0;
+
+ /* Enqueues a low-priority job that will clean up dead PIDs from our list of PIDs to watch and subscribe to new
+ * PIDs that might have appeared. We do this in a delayed job because the work might be quite slow, as it
+ * involves issuing kill(pid, 0) on all processes we watch. */
+
+ if (!u->rewatch_pids_event_source) {
+ _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+
+ r = sd_event_add_defer(u->manager->event, &s, on_rewatch_pids_event, u);
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate event source for tidying watched PIDs: %m");
+
+ r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE);
+ if (r < 0)
+ return log_error_errno(r, "Failed to adjust priority of event source for tidying watched PIDs: m");
+
+ (void) sd_event_source_set_description(s, "tidy-watch-pids");
+
+ u->rewatch_pids_event_source = TAKE_PTR(s);
+ }
+
+ r = sd_event_source_set_enabled(u->rewatch_pids_event_source, SD_EVENT_ONESHOT);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable event source for tidying watched PIDs: %m");
+
+ return 0;
+}
+
+void unit_dequeue_rewatch_pids(Unit *u) {
+ int r;
+ assert(u);
+
+ if (!u->rewatch_pids_event_source)
+ return;
+
+ r = sd_event_source_set_enabled(u->rewatch_pids_event_source, SD_EVENT_OFF);
+ if (r < 0)
+ log_warning_errno(r, "Failed to disable event source for tidying watched PIDs, ignoring: %m");
+
+ u->rewatch_pids_event_source = sd_event_source_unref(u->rewatch_pids_event_source);
+}
+
bool unit_job_is_applicable(Unit *u, JobType j) {
assert(u);
assert(j >= 0 && j < _JOB_TYPE_MAX);
@@ -2724,8 +2770,8 @@ static int unit_add_dependency_hashmap(
if (info.data) {
/* Entry already exists. Add in our mask. */
- if ((info.origin_mask & origin_mask) == info.origin_mask &&
- (info.destination_mask & destination_mask) == info.destination_mask)
+ if (FLAGS_SET(origin_mask, info.origin_mask) &&
+ FLAGS_SET(destination_mask, info.destination_mask))
return 0; /* NOP */
info.origin_mask |= origin_mask;
@@ -3631,7 +3677,6 @@ void unit_deserialize_skip(FILE *f) {
}
}
-
int unit_add_node_dependency(Unit *u, const char *what, bool wants, UnitDependency dep, UnitDependencyMask mask) {
Unit *device;
_cleanup_free_ char *e = NULL;
@@ -3683,8 +3728,7 @@ int unit_coldplug(Unit *u) {
assert(u);
- /* Make sure we don't enter a loop, when coldplugging
- * recursively. */
+ /* Make sure we don't enter a loop, when coldplugging recursively. */
if (u->coldplugged)
return 0;
@@ -3712,6 +3756,13 @@ int unit_coldplug(Unit *u) {
return r;
}
+void unit_catchup(Unit *u) {
+ assert(u);
+
+ if (UNIT_VTABLE(u)->catchup)
+ UNIT_VTABLE(u)->catchup(u);
+}
+
static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_masked) {
struct stat st;
@@ -3846,7 +3897,7 @@ int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
}
static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
- Set *pid_set;
+ _cleanup_set_free_ Set *pid_set = NULL;
int r;
pid_set = set_new(NULL);
@@ -3857,20 +3908,16 @@ static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
if (main_pid > 0) {
r = set_put(pid_set, PID_TO_PTR(main_pid));
if (r < 0)
- goto fail;
+ return NULL;
}
if (control_pid > 0) {
r = set_put(pid_set, PID_TO_PTR(control_pid));
if (r < 0)
- goto fail;
+ return NULL;
}
- return pid_set;
-
-fail:
- set_free(pid_set);
- return NULL;
+ return TAKE_PTR(pid_set);
}
int unit_kill_common(
@@ -4020,8 +4067,7 @@ static int user_from_unit_name(Unit *u, char **ret) {
return r;
if (valid_user_group_name(n)) {
- *ret = n;
- n = NULL;
+ *ret = TAKE_PTR(n);
return 0;
}
@@ -4223,7 +4269,7 @@ char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf) {
char* unit_concat_strv(char **l, UnitWriteFlags flags) {
_cleanup_free_ char *result = NULL;
size_t n = 0, allocated = 0;
- char **i, *ret;
+ char **i;
/* Takes a list of strings, escapes them, and concatenates them. This may be used to format command lines in a
* way suitable for ExecStart= stanzas */
@@ -4258,10 +4304,7 @@ char* unit_concat_strv(char **l, UnitWriteFlags flags) {
result[n] = 0;
- ret = result;
- result = NULL;
-
- return ret;
+ return TAKE_PTR(result);
}
int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data) {
@@ -4565,7 +4608,8 @@ int unit_kill_context(
}
int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) {
- char prefix[strlen(path) + 1], *p;
+ _cleanup_free_ char *p = NULL;
+ char *prefix;
UnitDependencyInfo di;
int r;
@@ -4588,34 +4632,30 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask)
if (!p)
return -ENOMEM;
- path_kill_slashes(p);
+ path = path_simplify(p, false);
- if (!path_is_normalized(p)) {
- free(p);
+ if (!path_is_normalized(path))
return -EPERM;
- }
- if (hashmap_contains(u->requires_mounts_for, p)) {
- free(p);
+ if (hashmap_contains(u->requires_mounts_for, path))
return 0;
- }
di = (UnitDependencyInfo) {
.origin_mask = mask
};
- r = hashmap_put(u->requires_mounts_for, p, di.data);
- if (r < 0) {
- free(p);
+ r = hashmap_put(u->requires_mounts_for, path, di.data);
+ if (r < 0)
return r;
- }
+ p = NULL;
- PATH_FOREACH_PREFIX_MORE(prefix, p) {
+ prefix = alloca(strlen(path) + 1);
+ PATH_FOREACH_PREFIX_MORE(prefix, path) {
Set *x;
x = hashmap_get(u->manager->units_requiring_mounts_for, prefix);
if (!x) {
- char *q;
+ _cleanup_free_ char *q = NULL;
r = hashmap_ensure_allocated(&u->manager->units_requiring_mounts_for, &path_hash_ops);
if (r < 0)
@@ -4626,17 +4666,15 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask)
return -ENOMEM;
x = set_new(NULL);
- if (!x) {
- free(q);
+ if (!x)
return -ENOMEM;
- }
r = hashmap_put(u->manager->units_requiring_mounts_for, q, x);
if (r < 0) {
- free(q);
set_free(x);
return r;
}
+ q = NULL;
}
r = set_put(x, u);
@@ -4724,8 +4762,7 @@ void unit_warn_if_dir_nonempty(Unit *u, const char* where) {
LOG_UNIT_ID(u),
LOG_UNIT_INVOCATION_ID(u),
LOG_UNIT_MESSAGE(u, "Directory %s to mount over is not empty, mounting anyway.", where),
- "WHERE=%s", where,
- NULL);
+ "WHERE=%s", where);
}
int unit_fail_if_noncanonical(Unit *u, const char* where) {
@@ -4751,8 +4788,7 @@ int unit_fail_if_noncanonical(Unit *u, const char* where) {
LOG_UNIT_ID(u),
LOG_UNIT_INVOCATION_ID(u),
LOG_UNIT_MESSAGE(u, "Mount path %s is not canonical (contains a symlink).", where),
- "WHERE=%s", where,
- NULL);
+ "WHERE=%s", where);
return -ELOOP;
}
@@ -4763,9 +4799,8 @@ bool unit_is_pristine(Unit *u) {
/* Check if the unit already exists or is already around,
* in a number of different ways. Note that to cater for unit
* types such as slice, we are generally fine with units that
- * are marked UNIT_LOADED even though nothing was
- * actually loaded, as those unit types don't require a file
- * on disk to validly load. */
+ * are marked UNIT_LOADED even though nothing was actually
+ * loaded, as those unit types don't require a file on disk. */
return !(!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) ||
u->fragment_path ||
@@ -5218,6 +5253,9 @@ void unit_export_state_files(Unit *u) {
if (!MANAGER_IS_SYSTEM(u->manager))
return;
+ if (u->manager->test_run_flags != 0)
+ return;
+
/* Exports a couple of unit properties to /run/systemd/units/, so that journald can quickly query this data
* from there. Ideally, journald would use IPC to query this, like everybody else, but that's hard, as long as
* the IPC system itself and PID 1 also log to the journal.
@@ -5381,7 +5419,7 @@ int unit_pid_attachable(Unit *u, pid_t pid, sd_bus_error *error) {
/* Some extra safety check */
if (pid == 1 || pid == getpid_cached())
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process " PID_FMT " is a manager processs, refusing.", pid);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process " PID_FMT " is a manager process, refusing.", pid);
/* Don't even begin to bother with kernel threads */
r = is_kernel_thread(pid);
diff --git a/src/core/unit.h b/src/core/unit.h
index e903bf8ad7..b3131eba1b 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -1,34 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
-typedef struct Unit Unit;
-typedef struct UnitVTable UnitVTable;
-typedef struct UnitRef UnitRef;
-typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
-
#include "bpf-program.h"
#include "condition.h"
#include "emergency-action.h"
@@ -37,6 +13,8 @@ typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
#include "unit-name.h"
#include "cgroup.h"
+typedef struct UnitRef UnitRef;
+
typedef enum KillOperation {
KILL_TERMINATE,
KILL_TERMINATE_AND_LOG,
@@ -102,7 +80,7 @@ typedef enum UnitDependencyMask {
/* A dependency created because of data read from /proc/swaps and no other configuration source */
UNIT_DEPENDENCY_PROC_SWAP = 1 << 7,
- _UNIT_DEPENDENCY_MASK_FULL = (1 << 8) - 1,
+ _UNIT_DEPENDENCY_MASK_FULL = (1 << 8) - 1,
} UnitDependencyMask;
/* The Unit's dependencies[] hashmaps use this structure as value. It has the same size as a void pointer, and thus can
@@ -133,7 +111,7 @@ typedef enum UnitCGroupBPFState {
UNIT_CGROUP_BPF_INVALIDATED = -1,
} UnitCGroupBPFState;
-struct Unit {
+typedef struct Unit {
Manager *manager;
UnitType type;
@@ -231,6 +209,9 @@ struct Unit {
/* cgroup empty queue */
LIST_FIELDS(Unit, cgroup_empty_queue);
+ /* Target dependencies queue */
+ LIST_FIELDS(Unit, target_deps_queue);
+
/* PIDs we keep an eye on. Note that a unit might have many
* more, but these are the ones we care enough about to
* process SIGCHLD for */
@@ -292,6 +273,10 @@ struct Unit {
uint64_t ip_accounting_extra[_CGROUP_IP_ACCOUNTING_METRIC_MAX];
+ /* Low-priority event source which is used to remove watched PIDs that have gone away, and subscribe to any new
+ * ones which might have appeared. */
+ sd_event_source *rewatch_pids_event_source;
+
/* How to start OnFailure units */
JobMode on_failure_job_mode;
@@ -336,6 +321,7 @@ struct Unit {
bool in_gc_queue:1;
bool in_cgroup_realize_queue:1;
bool in_cgroup_empty_queue:1;
+ bool in_target_deps_queue:1;
bool sent_dbus_new_signal:1;
@@ -367,13 +353,13 @@ struct Unit {
/* When writing transient unit files, stores which section we stored last. If < 0, we didn't write any yet. If
* == 0 we are in the [Unit] section, if > 0 we are in the unit type-specific section. */
int last_section_private:2;
-};
+} Unit;
-struct UnitStatusMessageFormats {
+typedef struct UnitStatusMessageFormats {
const char *starting_stopping[2];
const char *finished_start_job[_JOB_RESULT_MAX];
const char *finished_stop_job[_JOB_RESULT_MAX];
-};
+} UnitStatusMessageFormats;
/* Flags used when writing drop-in files or transient unit files */
typedef enum UnitWriteFlags {
@@ -396,17 +382,9 @@ typedef enum UnitWriteFlags {
/* Returns true if neither persistent, nor runtime storage is requested, i.e. this is a check invocation only */
#define UNIT_WRITE_FLAGS_NOOP(flags) (((flags) & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0)
-#include "automount.h"
-#include "device.h"
-#include "path.h"
-#include "scope.h"
-#include "slice.h"
-#include "socket.h"
-#include "swap.h"
-#include "target.h"
-#include "timer.h"
-
-struct UnitVTable {
+#include "kill.h"
+
+typedef struct UnitVTable {
/* How much memory does an object of this unit type need */
size_t object_size;
@@ -453,10 +431,14 @@ struct UnitVTable {
* UNIT_STUB if no configuration could be found. */
int (*load)(Unit *u);
- /* If a lot of units got created via enumerate(), this is
- * where to actually set the state and call unit_notify(). */
+ /* During deserialization we only record the intended state to return to. With coldplug() we actually put the
+ * deserialized state in effect. This is where unit_notify() should be called to start things up. */
int (*coldplug)(Unit *u);
+ /* This is called shortly after all units' coldplug() call was invoked. It's supposed to catch up state changes
+ * we missed so far (for example because they took place while we were reloading/reexecing) */
+ void (*catchup)(Unit *u);
+
void (*dump)(Unit *u, FILE *f, const char *prefix);
int (*start)(Unit *u);
@@ -532,6 +514,9 @@ struct UnitVTable {
/* Called whenever CLOCK_REALTIME made a jump */
void (*time_change)(Unit *u);
+ /* Called whenever /etc/localtime was modified */
+ void (*timezone_change)(Unit *u);
+
/* Returns the next timeout of a unit */
int (*get_timeout)(Unit *u, usec_t *timeout);
@@ -544,11 +529,15 @@ struct UnitVTable {
/* Returns true if the unit currently needs access to the console */
bool (*needs_console)(Unit *u);
- /* This is called for each unit type and should be used to
- * enumerate existing devices and load them. However,
- * everything that is loaded here should still stay in
- * inactive state. It is the job of the coldplug() call above
- * to put the units into the initial state. */
+ /* Like the enumerate() callback further down, but only enumerates the perpetual units, i.e. all units that
+ * unconditionally exist and are always active. The main reason to keep both enumeration functions separate is
+ * philosophical: the state of perpetual units should be put in place by coldplug(), while the state of those
+ * discovered through regular enumeration should be put in place by catchup(), see below. */
+ void (*enumerate_perpetual)(Manager *m);
+
+ /* This is called for each unit type and should be used to enumerate units already existing in the system
+ * internally and load them. However, everything that is loaded here should still stay in inactive state. It is
+ * the job of the catchup() call above to put the units into the discovered state. */
void (*enumerate)(Manager *m);
/* Type specific cleanups. */
@@ -570,9 +559,12 @@ struct UnitVTable {
/* True if cgroup delegation is permissible */
bool can_delegate:1;
+ /* True if units of this type shall be startable only once and then never again */
+ bool once_only:1;
+
/* True if queued jobs of this type should be GC'ed if no other job needs them anymore */
bool gc_jobs:1;
-};
+} UnitVTable;
extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
@@ -596,20 +588,9 @@ extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
#define UNIT_TRIGGER(u) ((Unit*) hashmap_first_key((u)->dependencies[UNIT_TRIGGERS]))
-DEFINE_CAST(SERVICE, Service);
-DEFINE_CAST(SOCKET, Socket);
-DEFINE_CAST(TARGET, Target);
-DEFINE_CAST(DEVICE, Device);
-DEFINE_CAST(MOUNT, Mount);
-DEFINE_CAST(AUTOMOUNT, Automount);
-DEFINE_CAST(SWAP, Swap);
-DEFINE_CAST(TIMER, Timer);
-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);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Unit *, unit_free);
int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret);
int unit_add_name(Unit *u, const char *name);
@@ -631,6 +612,7 @@ void unit_add_to_load_queue(Unit *u);
void unit_add_to_dbus_queue(Unit *u);
void unit_add_to_cleanup_queue(Unit *u);
void unit_add_to_gc_queue(Unit *u);
+void unit_add_to_target_deps_queue(Unit *u);
int unit_merge(Unit *u, Unit *other);
int unit_merge_by_name(Unit *u, const char *other);
@@ -666,13 +648,19 @@ int unit_reload(Unit *u);
int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error);
int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, sd_bus_error *error);
-void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
+typedef enum UnitNotifyFlags {
+ UNIT_NOTIFY_RELOAD_FAILURE = 1 << 0,
+ UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1,
+} UnitNotifyFlags;
+
+void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags);
int unit_watch_pid(Unit *u, pid_t pid);
void unit_unwatch_pid(Unit *u, pid_t pid);
void unit_unwatch_all_pids(Unit *u);
-void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2);
+int unit_enqueue_rewatch_pids(Unit *u);
+void unit_dequeue_rewatch_pids(Unit *u);
int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name);
int unit_watch_bus_name(Unit *u, const char *name);
@@ -701,6 +689,7 @@ void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *v
int unit_add_node_dependency(Unit *u, const char *what, bool wants, UnitDependency d, UnitDependencyMask mask);
int unit_coldplug(Unit *u);
+void unit_catchup(Unit *u);
void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0);
void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t);
diff --git a/src/coredump/coredump-vacuum.c b/src/coredump/coredump-vacuum.c
index e27512167c..6ce5dfc71d 100644
--- a/src/coredump/coredump-vacuum.c
+++ b/src/coredump/coredump-vacuum.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/statvfs.h>
@@ -227,8 +209,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
if (r < 0)
return log_oom();
- c = n;
- n = NULL;
+ c = TAKE_PTR(n);
}
c->n_files++;
diff --git a/src/coredump/coredump-vacuum.h b/src/coredump/coredump-vacuum.h
index c61d08f79c..0db116736c 100644
--- a/src/coredump/coredump-vacuum.h
+++ b/src/coredump/coredump-vacuum.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <sys/types.h>
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index e924750d1b..20a1cbdd45 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
@@ -154,7 +136,12 @@ static int parse_config(void) {
}
static inline uint64_t storage_size_max(void) {
- return arg_storage == COREDUMP_STORAGE_EXTERNAL ? arg_external_size_max : arg_journal_size_max;
+ if (arg_storage == COREDUMP_STORAGE_EXTERNAL)
+ return arg_external_size_max;
+ if (arg_storage == COREDUMP_STORAGE_JOURNAL)
+ return arg_journal_size_max;
+ assert(arg_storage == COREDUMP_STORAGE_NONE);
+ return 0;
}
static int fix_acl(int fd, uid_t uid) {
@@ -336,7 +323,7 @@ static int save_external_coredump(
_cleanup_free_ char *fn = NULL, *tmp = NULL;
_cleanup_close_ int fd = -1;
- uint64_t rlimit, max_size;
+ uint64_t rlimit, process_limit, max_size;
struct stat st;
uid_t uid;
int r;
@@ -363,8 +350,14 @@ static int save_external_coredump(
return -EBADSLT;
}
+ process_limit = MAX(arg_process_size_max, storage_size_max());
+ if (process_limit == 0) {
+ log_debug("Limits for coredump processing and storage are both 0, not dumping core.");
+ return -EBADSLT;
+ }
+
/* Never store more than the process configured, or than we actually shall keep or process */
- max_size = MIN(rlimit, MAX(arg_process_size_max, storage_size_max()));
+ max_size = MIN(rlimit, process_limit);
r = make_filename(context, &fn);
if (r < 0)
@@ -386,8 +379,7 @@ static int save_external_coredump(
log_struct(LOG_INFO,
LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size),
"SIZE_LIMIT=%zu", max_size,
- "MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR);
if (fstat(fd, &st) < 0) {
log_error_errno(errno, "Failed to fstat core file %s: %m", coredump_tmpfile_name(tmp));
@@ -432,14 +424,11 @@ static int save_external_coredump(
if (tmp)
unlink_noerrno(tmp);
- *ret_filename = fn_compressed; /* compressed */
- *ret_node_fd = fd_compressed; /* compressed */
- *ret_data_fd = fd; /* uncompressed */
+ *ret_filename = TAKE_PTR(fn_compressed); /* compressed */
+ *ret_node_fd = TAKE_FD(fd_compressed); /* compressed */
+ *ret_data_fd = TAKE_FD(fd); /* uncompressed */
*ret_size = (uint64_t) st.st_size; /* uncompressed */
- fn_compressed = NULL;
- fd = fd_compressed = -1;
-
return 0;
fail_compressed:
@@ -454,14 +443,11 @@ uncompressed:
if (r < 0)
goto fail;
- *ret_filename = fn;
- *ret_data_fd = fd;
+ *ret_filename = TAKE_PTR(fn);
+ *ret_data_fd = TAKE_FD(fd);
*ret_node_fd = -1;
*ret_size = (uint64_t) st.st_size;
- fn = NULL;
- fd = -1;
-
return 0;
fail:
@@ -497,11 +483,9 @@ static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_s
return -EIO;
}
- *ret = field;
+ *ret = TAKE_PTR(field);
*ret_size = size + 9;
- field = NULL;
-
return 0;
}
@@ -584,8 +568,7 @@ static int compose_open_fds(pid_t pid, char **open_fds) {
if (errno > 0)
return -errno;
- *open_fds = buffer;
- buffer = NULL;
+ *open_fds = TAKE_PTR(buffer);
return 0;
}
@@ -863,21 +846,18 @@ static void map_context_fields(const struct iovec *iovec, const char* context[])
assert(context);
for (i = 0; i < ELEMENTSOF(context_field_names); i++) {
- size_t l;
+ char *p;
if (!context_field_names[i])
continue;
- l = strlen(context_field_names[i]);
- if (iovec->iov_len < l)
- continue;
-
- if (memcmp(iovec->iov_base, context_field_names[i], l) != 0)
+ p = memory_startswith(iovec->iov_base, iovec->iov_len, context_field_names[i]);
+ if (!p)
continue;
/* Note that these strings are NUL terminated, because we made sure that a trailing NUL byte is in the
* buffer, though not included in the iov_len count. (see below) */
- context[i] = (char*) iovec->iov_base + l;
+ context[i] = p;
break;
}
}
@@ -932,7 +912,7 @@ static int process_socket(int fd) {
mh.msg_iov = iovec + n_iovec;
- n = recvmsg(fd, &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
+ n = recvmsg(fd, &mh, MSG_CMSG_CLOEXEC);
if (n < 0) {
free(iovec[n_iovec].iov_base);
r = log_error_errno(errno, "Failed to receive datagram: %m");
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index a4cc9c1db3..99d07c14fb 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <getopt.h>
@@ -51,32 +33,24 @@
#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
+#include "verbs.h"
#define SHORT_BUS_CALL_TIMEOUT_USEC (3 * USEC_PER_SEC)
static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY;
-
-static enum {
- ACTION_NONE,
- ACTION_INFO,
- ACTION_LIST,
- ACTION_DUMP,
- ACTION_GDB,
-} arg_action = ACTION_LIST;
static const char* arg_field = NULL;
+static const char *arg_debugger = NULL;
static const char *arg_directory = NULL;
static bool arg_no_pager = false;
static int arg_no_legend = false;
static int arg_one = false;
static FILE* arg_output = NULL;
static bool arg_reverse = false;
-static char** arg_matches = NULL;
static bool arg_quiet = false;
static int add_match(sd_journal *j, const char *match) {
_cleanup_free_ char *p = NULL;
- char *pattern = NULL;
- const char* prefix;
+ const char* prefix, *pattern;
pid_t pid;
int r;
@@ -99,10 +73,11 @@ static int add_match(sd_journal *j, const char *match) {
r = sd_journal_add_match(j, pattern, 0);
if (r < 0)
return log_error_errno(r, "Failed to add match \"%s\": %m", match);
+
return 0;
}
-static int add_matches(sd_journal *j) {
+static int add_matches(sd_journal *j, char **matches) {
char **match;
int r;
@@ -114,7 +89,7 @@ static int add_matches(sd_journal *j) {
if (r < 0)
return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR);
- STRV_FOREACH(match, arg_matches) {
+ STRV_FOREACH(match, matches) {
r = add_match(j, *match);
if (r < 0)
return r;
@@ -123,28 +98,67 @@ static int add_matches(sd_journal *j) {
return 0;
}
-static void help(void) {
+static int acquire_journal(sd_journal **ret, char **matches) {
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
+ int r;
+
+ assert(ret);
+
+ if (arg_directory) {
+ r = sd_journal_open_directory(&j, arg_directory, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
+ } else {
+ r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
+ if (r < 0)
+ return log_error_errno(r, "Failed to open journal: %m");
+ }
+
+ r = journal_access_check_and_warn(j, arg_quiet, true);
+ if (r < 0)
+ return r;
+
+ r = add_matches(j, matches);
+ if (r < 0)
+ return r;
+
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *filter;
+
+ filter = journal_make_match_string(j);
+ log_debug("Journal filter: %s", filter);
+ }
+
+ *ret = TAKE_PTR(j);
+
+ return 0;
+}
+
+static int help(void) {
printf("%s [OPTIONS...]\n\n"
"List or retrieve coredumps from the journal.\n\n"
"Flags:\n"
- " -h --help Show this help\n"
- " --version Print version string\n"
- " --no-pager Do not pipe output into a pager\n"
- " --no-legend Do not print the column headers.\n"
- " -1 Show information about most recent entry only\n"
- " -S --since=DATE Only print coredumps since the date\n"
- " -U --until=DATE Only print coredumps until the date\n"
- " -r --reverse Show the newest entries first\n"
- " -F --field=FIELD List all values a certain field takes\n"
- " -o --output=FILE Write output to FILE\n"
- " -D --directory=DIR Use journal files from directory\n\n"
- " -q --quiet Do not show info messages and privilege warning\n"
+ " -h --help Show this help\n"
+ " --version Print version string\n"
+ " --no-pager Do not pipe output into a pager\n"
+ " --no-legend Do not print the column headers\n"
+ " --debugger=DEBUGGER Use the given debugger\n"
+ " -1 Show information about most recent entry only\n"
+ " -S --since=DATE Only print coredumps since the date\n"
+ " -U --until=DATE Only print coredumps until the date\n"
+ " -r --reverse Show the newest entries first\n"
+ " -F --field=FIELD List all values a certain field takes\n"
+ " -o --output=FILE Write output to FILE\n"
+ " -D --directory=DIR Use journal files from directory\n\n"
+ " -q --quiet Do not show info messages and privilege warning\n"
"Commands:\n"
" list [MATCHES...] List available coredumps (default)\n"
" info [MATCHES...] Show detailed information about one or more coredumps\n"
" dump [MATCHES...] Print first matching coredump to stdout\n"
- " gdb [MATCHES...] Start gdb for the first matching coredump\n"
+ " debug [MATCHES...] Start a debugger for the first matching coredump\n"
, program_invocation_short_name);
+
+ return 0;
}
static int parse_argv(int argc, char *argv[]) {
@@ -152,6 +166,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_NO_LEGEND,
+ ARG_DEBUGGER,
};
int c, r;
@@ -161,6 +176,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "version" , no_argument, NULL, ARG_VERSION },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
+ { "debugger", required_argument, NULL, ARG_DEBUGGER },
{ "output", required_argument, NULL, 'o' },
{ "field", required_argument, NULL, 'F' },
{ "directory", required_argument, NULL, 'D' },
@@ -177,12 +193,9 @@ static int parse_argv(int argc, char *argv[]) {
while ((c = getopt_long(argc, argv, "ho:F:1D:rS:U:q", options, NULL)) >= 0)
switch(c) {
case 'h':
- arg_action = ACTION_NONE;
- help();
- return 0;
+ return help();
case ARG_VERSION:
- arg_action = ACTION_NONE;
return version();
case ARG_NO_PAGER:
@@ -193,9 +206,13 @@ static int parse_argv(int argc, char *argv[]) {
arg_no_legend = true;
break;
+ case ARG_DEBUGGER:
+ arg_debugger = optarg;
+ break;
+
case 'o':
if (arg_output) {
- log_error("cannot set output more than once");
+ log_error("Cannot set output more than once.");
return -EINVAL;
}
@@ -219,7 +236,7 @@ static int parse_argv(int argc, char *argv[]) {
case 'F':
if (arg_field) {
- log_error("cannot use --field/-F more than once");
+ log_error("Cannot use --field/-F more than once.");
return -EINVAL;
}
arg_field = optarg;
@@ -254,31 +271,7 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- if (optind < argc) {
- const char *cmd = argv[optind++];
- if (streq(cmd, "list"))
- arg_action = ACTION_LIST;
- else if (streq(cmd, "dump"))
- arg_action = ACTION_DUMP;
- else if (streq(cmd, "gdb"))
- arg_action = ACTION_GDB;
- else if (streq(cmd, "info"))
- arg_action = ACTION_INFO;
- else {
- log_error("Unknown action '%s'", cmd);
- return -EINVAL;
- }
- }
-
- if (arg_field && arg_action != ACTION_LIST) {
- log_error("Option --field/-F only makes sense with list");
- return -EINVAL;
- }
-
- if (optind < argc)
- arg_matches = argv + optind;
-
- return 0;
+ return 1;
}
static int retrieve(const void *data,
@@ -631,10 +624,10 @@ static int focus(sd_journal *j) {
return r;
}
-static int print_entry(sd_journal *j, unsigned n_found) {
+static int print_entry(sd_journal *j, unsigned n_found, bool verb_is_info) {
assert(j);
- if (arg_action == ACTION_INFO)
+ if (verb_is_info)
return print_info(stdout, j, n_found);
else if (arg_field)
return print_field(stdout, j);
@@ -642,11 +635,19 @@ static int print_entry(sd_journal *j, unsigned n_found) {
return print_list(stdout, j, n_found);
}
-static int dump_list(sd_journal *j) {
+static int dump_list(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
unsigned n_found = 0;
+ bool verb_is_info;
int r;
- assert(j);
+ verb_is_info = (argc >= 1 && streq(argv[0], "info"));
+
+ r = acquire_journal(&j, argv + 1);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_no_pager, false);
/* The coredumps are likely to compressed, and for just
* listing them we don't need to decompress them, so let's
@@ -658,7 +659,7 @@ static int dump_list(sd_journal *j) {
if (r < 0)
return r;
- return print_entry(j, 0);
+ return print_entry(j, 0, verb_is_info);
} else {
if (arg_since != USEC_INFINITY && !arg_reverse)
r = sd_journal_seek_realtime_usec(j, arg_since);
@@ -703,7 +704,7 @@ static int dump_list(sd_journal *j) {
continue;
}
- r = print_entry(j, n_found++);
+ r = print_entry(j, n_found++, verb_is_info);
if (r < 0)
return r;
}
@@ -752,8 +753,7 @@ static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp)
return log_error_errno(errno, "File \"%s\" is not readable: %m", filename);
if (path && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) {
- *path = filename;
- filename = NULL;
+ *path = TAKE_PTR(filename);
return 0;
}
@@ -856,10 +856,18 @@ error:
return r;
}
-static int dump_core(sd_journal* j) {
+static int dump_core(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
int r;
- assert(j);
+ if (arg_field) {
+ log_error("Option --field/-F only makes sense with list");
+ return -EINVAL;
+ }
+
+ r = acquire_journal(&j, argv + 1);
+ if (r < 0)
+ return r;
r = focus(j);
if (r < 0)
@@ -878,15 +886,33 @@ static int dump_core(sd_journal* j) {
return 0;
}
-static int run_gdb(sd_journal *j) {
+static int run_debug(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
_cleanup_free_ char *exe = NULL, *path = NULL;
bool unlink_path = false;
- const char *data;
+ const char *data, *fork_name;
size_t len;
pid_t pid;
int r;
- assert(j);
+ if (!arg_debugger) {
+ char *env_debugger;
+
+ env_debugger = getenv("SYSTEMD_DEBUGGER");
+ if (env_debugger)
+ arg_debugger = env_debugger;
+ else
+ arg_debugger = "gdb";
+ }
+
+ if (arg_field) {
+ log_error("Option --field/-F only makes sense with list");
+ return -EINVAL;
+ }
+
+ r = acquire_journal(&j, argv + 1);
+ if (r < 0)
+ return r;
r = focus(j);
if (r < 0)
@@ -924,17 +950,19 @@ static int run_gdb(sd_journal *j) {
/* Don't interfere with gdb and its handling of SIGINT. */
(void) ignore_signals(SIGINT, -1);
- r = safe_fork("(gdb)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+ fork_name = strjoina("(", arg_debugger, ")");
+
+ r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
goto finish;
if (r == 0) {
- execlp("gdb", "gdb", exe, path, NULL);
+ execlp(arg_debugger, arg_debugger, exe, "-c", path, NULL);
log_open();
- log_error_errno(errno, "Failed to invoke gdb: %m");
+ log_error_errno(errno, "Failed to invoke %s: %m", arg_debugger);
_exit(EXIT_FAILURE);
}
- r = wait_for_terminate_and_check("gdb", pid, WAIT_LOG_ABNORMAL);
+ r = wait_for_terminate_and_check(arg_debugger, pid, WAIT_LOG_ABNORMAL);
finish:
(void) default_signals(SIGINT, -1);
@@ -1007,73 +1035,36 @@ static int check_units_active(void) {
return c;
}
+static int coredumpctl_main(int argc, char *argv[]) {
+
+ static const Verb verbs[] = {
+ { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, dump_list },
+ { "info", VERB_ANY, VERB_ANY, 0, dump_list },
+ { "dump", VERB_ANY, VERB_ANY, 0, dump_core },
+ { "debug", VERB_ANY, VERB_ANY, 0, run_debug },
+ { "gdb", VERB_ANY, VERB_ANY, 0, run_debug },
+ {}
+ };
+
+ return dispatch_verb(argc, argv, verbs, NULL);
+}
+
int main(int argc, char *argv[]) {
- _cleanup_(sd_journal_closep) sd_journal*j = NULL;
- int r = 0, units_active;
+ int r, units_active;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
- if (r < 0)
- goto end;
-
- if (arg_action == ACTION_NONE)
+ if (r <= 0)
goto end;
sigbus_install();
- if (arg_directory) {
- r = sd_journal_open_directory(&j, arg_directory, 0);
- if (r < 0) {
- log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory);
- goto end;
- }
- } else {
- r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
- if (r < 0) {
- log_error_errno(r, "Failed to open journal: %m");
- goto end;
- }
- }
-
- r = journal_access_check_and_warn(j, arg_quiet, true);
- if (r < 0)
- goto end;
-
- r = add_matches(j);
- if (r < 0)
- goto end;
-
- if (DEBUG_LOGGING) {
- _cleanup_free_ char *filter;
-
- filter = journal_make_match_string(j);
- log_debug("Journal filter: %s", filter);
- }
-
units_active = check_units_active(); /* error is treated the same as 0 */
- switch(arg_action) {
-
- case ACTION_LIST:
- case ACTION_INFO:
- pager_open(arg_no_pager, false);
- r = dump_list(j);
- break;
-
- case ACTION_DUMP:
- r = dump_core(j);
- break;
-
- case ACTION_GDB:
- r = run_gdb(j);
- break;
-
- default:
- assert_not_reached("Shouldn't be here");
- }
+ r = coredumpctl_main(argc, argv);
if (units_active > 0)
printf("%s-- Notice: %d systemd-coredump@.service %s, output may be incomplete.%s\n",
@@ -1083,8 +1074,7 @@ int main(int argc, char *argv[]) {
end:
pager_close();
- if (arg_output)
- fclose(arg_output);
+ safe_fclose(arg_output);
return r >= 0 ? r : EXIT_FAILURE;
}
diff --git a/src/coredump/meson.build b/src/coredump/meson.build
index 4e31e7c7c2..bfba7ef58c 100644
--- a/src/coredump/meson.build
+++ b/src/coredump/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
systemd_coredump_sources = files('''
coredump.c
diff --git a/src/coredump/stacktrace.c b/src/coredump/stacktrace.c
index 95fd27b79a..dab4c1ad9b 100644
--- a/src/coredump/stacktrace.c
+++ b/src/coredump/stacktrace.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dwarf.h>
#include <elfutils/libdwfl.h>
@@ -184,8 +166,7 @@ int coredump_make_stack_trace(int fd, const char *executable, char **ret) {
c.f = safe_fclose(c.f);
- *ret = buf;
- buf = NULL;
+ *ret = TAKE_PTR(buf);
r = 0;
diff --git a/src/coredump/stacktrace.h b/src/coredump/stacktrace.h
index d435878b44..52900424a7 100644
--- a/src/coredump/stacktrace.h
+++ b/src/coredump/stacktrace.h
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int coredump_make_stack_trace(int fd, const char *executable, char **ret);
diff --git a/src/coredump/test-coredump-vacuum.c b/src/coredump/test-coredump-vacuum.c
index 0836825b07..75fb442873 100644
--- a/src/coredump/test-coredump-vacuum.c
+++ b/src/coredump/test-coredump-vacuum.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdlib.h>
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index acde2a6a32..f5a81829b9 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio_ext.h>
@@ -173,7 +155,6 @@ static int create_disk(
"RequiresMountsFor=%s\n",
u_escaped);
-
r = generator_write_timeouts(arg_dest, device, name, options, &filtered);
if (r < 0)
return r;
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index 7255ff418c..832168184a 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <mntent.h>
@@ -402,8 +384,7 @@ static int get_password(const char *vol, const char *src, usec_t until, bool acc
*p = c;
}
- *ret = passwords;
- passwords = NULL;
+ *ret = TAKE_PTR(passwords);
return 0;
}
diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c
index 61c890d05a..dd6ab94fa2 100644
--- a/src/debug-generator/debug-generator.c
+++ b/src/debug-generator/debug-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "mkdir.h"
@@ -45,7 +27,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value))
return 0;
- r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n);
+ r = unit_name_mangle(value, UNIT_NAME_MANGLE_WARN, &n);
if (r < 0)
return log_error_errno(r, "Failed to glob unit name: %m");
@@ -59,7 +41,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value))
return 0;
- r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n);
+ r = unit_name_mangle(value, UNIT_NAME_MANGLE_WARN, &n);
if (r < 0)
return log_error_errno(r, "Failed to glob unit name: %m");
diff --git a/src/delta/delta.c b/src/delta/delta.c
index 4fe89ff9b0..21cce7e8b5 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
@@ -75,12 +56,12 @@ static bool arg_no_pager = false;
static int arg_diff = -1;
static enum {
- SHOW_MASKED = 1 << 0,
+ SHOW_MASKED = 1 << 0,
SHOW_EQUIVALENT = 1 << 1,
SHOW_REDIRECTED = 1 << 2,
SHOW_OVERRIDDEN = 1 << 3,
- SHOW_UNCHANGED = 1 << 4,
- SHOW_EXTENDED = 1 << 5,
+ SHOW_UNCHANGED = 1 << 4,
+ SHOW_EXTENDED = 1 << 5,
SHOW_DEFAULTS =
(SHOW_MASKED | SHOW_EQUIVALENT | SHOW_REDIRECTED | SHOW_OVERRIDDEN | SHOW_EXTENDED)
@@ -90,11 +71,11 @@ static int equivalent(const char *a, const char *b) {
_cleanup_free_ char *x = NULL, *y = NULL;
int r;
- r = chase_symlinks(a, NULL, 0, &x);
+ r = chase_symlinks(a, NULL, CHASE_TRAIL_SLASH, &x);
if (r < 0)
return r;
- r = chase_symlinks(b, NULL, 0, &y);
+ r = chase_symlinks(b, NULL, CHASE_TRAIL_SLASH, &y);
if (r < 0)
return r;
@@ -662,13 +643,13 @@ int main(int argc, char *argv[]) {
else if (arg_diff)
arg_flags |= SHOW_OVERRIDDEN;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (optind < argc) {
int i;
for (i = optind; i < argc; i++) {
- path_kill_slashes(argv[i]);
+ path_simplify(argv[i], false);
k = process_suffix_chop(argv[i]);
if (k < 0)
diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c
index 00235742de..e8c6362a9c 100644
--- a/src/detect-virt/detect-virt.c
+++ b/src/detect-virt/detect-virt.c
@@ -1,28 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdlib.h>
+#include "string-table.h"
#include "util.h"
#include "virt.h"
@@ -45,6 +28,7 @@ static void help(void) {
" -r --chroot Detect whether we are run in a chroot() environment\n"
" --private-users Only detect whether we are running in a user namespace\n"
" -q --quiet Don't output anything, just set return value\n"
+ " --list List all known and detectable types of virtualization\n"
, program_invocation_short_name);
}
@@ -53,6 +37,7 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_PRIVATE_USERS,
+ ARG_LIST,
};
static const struct option options[] = {
@@ -63,6 +48,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "chroot", no_argument, NULL, 'r' },
{ "private-users", no_argument, NULL, ARG_PRIVATE_USERS },
{ "quiet", no_argument, NULL, 'q' },
+ { "list", no_argument, NULL, ARG_LIST },
{}
};
@@ -102,6 +88,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_mode = ONLY_CHROOT;
break;
+ case ARG_LIST:
+ DUMP_STRING_TABLE(virtualization, int, _VIRTUALIZATION_MAX);
+ return 0;
+
case '?':
return -EINVAL;
diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c
index c8fb1c80d7..0adeee6691 100644
--- a/src/dissect/dissect.c
+++ b/src/dissect/dissect.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stdio.h>
@@ -202,31 +184,9 @@ int main(int argc, char *argv[]) {
}
}
- r = dissect_image(d->fd, arg_root_hash, arg_root_hash_size, arg_flags, &m);
- if (r == -ENOPKG) {
- log_error_errno(r, "Couldn't identify a suitable partition table or file system in %s.", arg_image);
- goto finish;
- }
- if (r == -EADDRNOTAVAIL) {
- log_error_errno(r, "No root partition for specified root hash found in %s.", arg_image);
- goto finish;
- }
- if (r == -ENOTUNIQ) {
- log_error_errno(r, "Multiple suitable root partitions found in image %s.", arg_image);
+ r = dissect_image_and_warn(d->fd, arg_image, arg_root_hash, arg_root_hash_size, arg_flags, &m);
+ if (r < 0)
goto finish;
- }
- if (r == -ENXIO) {
- log_error_errno(r, "No suitable root partition found in image %s.", arg_image);
- goto finish;
- }
- if (r == -EPROTONOSUPPORT) {
- log_error_errno(r, "Device %s is loopback block device with partition scanning turned off, please turn it on.", arg_image);
- goto finish;
- }
- if (r < 0) {
- log_error_errno(r, "Failed to dissect image: %m");
- goto finish;
- }
switch (arg_action) {
diff --git a/src/environment-d-generator/environment-d-generator.c b/src/environment-d-generator/environment-d-generator.c
index bb4d76da90..1719b69b98 100644
--- a/src/environment-d-generator/environment-d-generator.c
+++ b/src/environment-d-generator/environment-d-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-path.h"
@@ -45,8 +27,7 @@ static int environment_dirs(char ***ret) {
if (r < 0)
return r;
- *ret = dirs;
- dirs = NULL;
+ *ret = TAKE_PTR(dirs);
return 0;
}
diff --git a/src/escape/escape.c b/src/escape/escape.c
index 9c35b4663e..371ddbe02b 100644
--- a/src/escape/escape.c
+++ b/src/escape/escape.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Michael Biebl
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Michael Biebl
***/
#include <getopt.h>
@@ -217,7 +202,7 @@ int main(int argc, char *argv[]) {
break;
case ACTION_MANGLE:
- r = unit_name_mangle(*i, UNIT_NAME_NOGLOB, &e);
+ r = unit_name_mangle(*i, 0, &e);
if (r < 0) {
log_error_errno(r, "Failed to mangle name: %m");
goto finish;
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index d293e0a94a..41b212e32d 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -1,26 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <getopt.h>
-#include <shadow.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
@@ -47,6 +28,7 @@
#include "hostname-util.h"
#include "locale-util.h"
#include "mkdir.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
@@ -93,27 +75,16 @@ static bool press_any_key(void) {
static void print_welcome(void) {
_cleanup_free_ char *pretty_name = NULL;
- const char *os_release = NULL;
static bool done = false;
int r;
if (done)
return;
- os_release = prefix_roota(arg_root, "/etc/os-release");
- r = parse_env_file(os_release, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- NULL);
- if (r == -ENOENT) {
-
- os_release = prefix_roota(arg_root, "/usr/lib/os-release");
- r = parse_env_file(os_release, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- NULL);
- }
-
- if (r < 0 && r != -ENOENT)
- log_warning_errno(r, "Failed to read os-release file: %m");
+ r = parse_os_release(arg_root, "PRETTY_NAME", &pretty_name, NULL);
+ if (r < 0)
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to read os-release file, ignoring: %m");
printf("\nWelcome to your new installation of %s!\nPlease configure a few basic system settings:\n\n",
isempty(pretty_name) ? "GNU/Linux" : pretty_name);
@@ -124,13 +95,13 @@ static void print_welcome(void) {
}
static int show_menu(char **x, unsigned n_columns, unsigned width, unsigned percentage) {
- unsigned n, per_column, i, j;
unsigned break_lines, break_modulo;
+ size_t n, per_column, i, j;
assert(n_columns > 0);
n = strv_length(x);
- per_column = (n + n_columns - 1) / n_columns;
+ per_column = DIV_ROUND_UP(n, n_columns);
break_lines = lines();
if (break_lines > 2)
@@ -154,7 +125,7 @@ static int show_menu(char **x, unsigned n_columns, unsigned width, unsigned perc
if (!e)
return log_oom();
- printf("%4u) %-*s", j * per_column + i + 1, width, e);
+ printf("%4zu) %-*s", j * per_column + i + 1, width, e);
}
putchar('\n');
@@ -378,6 +349,10 @@ static int process_keymap(void) {
return 0;
}
+static bool timezone_is_valid_log_error(const char *name) {
+ return timezone_is_valid(name, LOG_ERR);
+}
+
static int prompt_timezone(void) {
_cleanup_strv_free_ char **zones = NULL;
int r;
@@ -401,7 +376,7 @@ static int prompt_timezone(void) {
putchar('\n');
- r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid, &arg_timezone);
+ r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid_log_error, &arg_timezone);
if (r < 0)
return r;
@@ -576,8 +551,7 @@ static int prompt_root_password(void) {
continue;
}
- arg_root_password = a;
- a = NULL;
+ arg_root_password = TAKE_PTR(a);
break;
}
@@ -586,6 +560,8 @@ static int prompt_root_password(void) {
static int write_root_shadow(const char *path, const struct spwd *p) {
_cleanup_fclose_ FILE *f = NULL;
+ int r;
+
assert(path);
assert(p);
@@ -594,9 +570,9 @@ static int write_root_shadow(const char *path, const struct spwd *p) {
if (!f)
return -errno;
- errno = 0;
- if (putspent(p, f) != 0)
- return errno > 0 ? -errno : -EIO;
+ r = putspent_sane(p, f);
+ if (r < 0)
+ return r;
return fflush_sync_and_check(f);
}
@@ -840,7 +816,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_TIMEZONE:
- if (!timezone_is_valid(optarg)) {
+ if (!timezone_is_valid(optarg, LOG_ERR)) {
log_error("Timezone %s is not valid.", optarg);
return -EINVAL;
}
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 97d824aca4..26fbd8bb03 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Holger Hans Peter Freyther
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Holger Hans Peter Freyther
***/
#include <errno.h>
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index fc58cba64f..482229b4a5 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <mntent.h>
@@ -237,7 +219,7 @@ static int write_dependency(FILE *f, const char *opts,
STRV_FOREACH(s, names) {
char *x;
- r = unit_name_mangle_with_suffix(*s, UNIT_NAME_NOGLOB, ".mount", &x);
+ r = unit_name_mangle_with_suffix(*s, 0, ".mount", &x);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
r = strv_consume(&units, x);
@@ -556,7 +538,7 @@ static int parse_fstab(bool initrd) {
return log_oom();
if (is_path(where)) {
- path_kill_slashes(where);
+ path_simplify(where, false);
/* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
* mount units, but causes problems since it historically worked to have symlinks in e.g.
diff --git a/src/fuzz/fuzz-dhcp-server.c b/src/fuzz/fuzz-dhcp-server.c
index ba903c7158..01fe350ca5 100644
--- a/src/fuzz/fuzz-dhcp-server.c
+++ b/src/fuzz/fuzz-dhcp-server.c
@@ -1,20 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright 2018 Jonathan Rudenberg
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "fuzz.h"
diff --git a/src/fuzz/fuzz-dns-server.options b/src/fuzz/fuzz-dhcp-server.options
index 5c330e5cec..5c330e5cec 100644
--- a/src/fuzz/fuzz-dns-server.options
+++ b/src/fuzz/fuzz-dhcp-server.options
diff --git a/src/fuzz/fuzz-dns-packet.c b/src/fuzz/fuzz-dns-packet.c
index 0f25081b22..c150c8184c 100644
--- a/src/fuzz/fuzz-dns-packet.c
+++ b/src/fuzz/fuzz-dns-packet.c
@@ -1,20 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright 2018 Jonathan Rudenberg
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "fuzz.h"
#include "resolved-dns-packet.h"
diff --git a/src/fuzz/fuzz-journal-remote.c b/src/fuzz/fuzz-journal-remote.c
new file mode 100644
index 0000000000..432c687bc0
--- /dev/null
+++ b/src/fuzz/fuzz-journal-remote.c
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "fuzz.h"
+
+#include <sys/mman.h>
+
+#include "sd-journal.h"
+
+#include "env-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "journal-remote.h"
+#include "logs-show.h"
+#include "memfd-util.h"
+#include "strv.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_fclose_ FILE *dev_null = NULL;
+ RemoteServer s = {};
+ char name[] = "/tmp/fuzz-journal-remote.XXXXXX.journal";
+ void *mem;
+ int fdin; /* will be closed by journal_remote handler after EOF */
+ _cleanup_close_ int fdout = -1;
+ sd_journal *j;
+ OutputMode mode;
+ int r;
+
+ if (size <= 2)
+ return 0;
+
+ assert_se((fdin = memfd_new_and_map("fuzz-journal-remote", size, &mem)) >= 0);
+ memcpy(mem, data, size);
+ assert_se(munmap(mem, size) == 0);
+
+ fdout = mkostemps(name, STRLEN(".journal"), O_CLOEXEC);
+ assert_se(fdout >= 0);
+
+ /* In */
+
+ assert_se(journal_remote_server_init(&s, name, JOURNAL_WRITE_SPLIT_NONE, false, false) >= 0);
+
+ assert_se(journal_remote_add_source(&s, fdin, (char*) "fuzz-data", false) > 0);
+
+ while (s.active) {
+ r = journal_remote_handle_raw_source(NULL, fdin, 0, &s);
+ assert_se(r >= 0);
+ }
+
+ journal_remote_server_destroy(&s);
+ assert_se(close(fdin) < 0 && errno == EBADF); /* Check that the fd is closed already */
+
+ /* Out */
+
+ r = sd_journal_open_files(&j, (const char**) STRV_MAKE(name), 0);
+ assert_se(r >= 0);
+
+ if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0)
+ assert_se(dev_null = fopen("/dev/null", "we"));
+
+ for (mode = 0; mode < _OUTPUT_MODE_MAX; mode++) {
+ if (!dev_null)
+ log_info("/* %s */", output_mode_to_string(mode));
+ r = show_journal(dev_null ?: stdout, j, mode, 0, 0, -1, 0, NULL);
+ assert_se(r >= 0);
+
+ r = sd_journal_seek_head(j);
+ assert_se(r >= 0);
+ }
+
+ sd_journal_close(j);
+ unlink(name);
+
+ return 0;
+}
diff --git a/src/fuzz/fuzz-journal-remote.options b/src/fuzz/fuzz-journal-remote.options
new file mode 100644
index 0000000000..678d526b1e
--- /dev/null
+++ b/src/fuzz/fuzz-journal-remote.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65536
diff --git a/src/fuzz/fuzz-main.c b/src/fuzz/fuzz-main.c
index 45e46907e2..d549dc95ff 100644
--- a/src/fuzz/fuzz-main.c
+++ b/src/fuzz/fuzz-main.c
@@ -1,20 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright 2018 Jonathan Rudenberg
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "log.h"
@@ -33,6 +17,9 @@ int main(int argc, char **argv) {
char *name;
log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
for (i = 1; i < argc; i++) {
_cleanup_free_ char *buf = NULL;
@@ -47,5 +34,6 @@ int main(int argc, char **argv) {
(void) LLVMFuzzerTestOneInput((uint8_t*)buf, size);
printf("ok\n");
}
+
return EXIT_SUCCESS;
}
diff --git a/src/fuzz/fuzz-unit-file.c b/src/fuzz/fuzz-unit-file.c
new file mode 100644
index 0000000000..93de50191b
--- /dev/null
+++ b/src/fuzz/fuzz-unit-file.c
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "conf-parser.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fuzz.h"
+#include "install.h"
+#include "load-fragment.h"
+#include "string-util.h"
+#include "unit.h"
+#include "utf8.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_free_ char *out = NULL; /* out should be freed after g */
+ size_t out_size;
+ _cleanup_fclose_ FILE *f = NULL, *g = NULL;
+ _cleanup_free_ char *p = NULL;
+ UnitType t;
+ _cleanup_(manager_freep) Manager *m = NULL;
+ Unit *u;
+ const char *name;
+ long offset;
+
+ if (size == 0)
+ return 0;
+
+ f = fmemopen((char*) data, size, "re");
+ assert_se(f);
+
+ if (read_line(f, LINE_MAX, &p) < 0)
+ return 0;
+
+ t = unit_type_from_string(p);
+ if (t < 0)
+ return 0;
+
+ if (!unit_vtable[t]->load)
+ return 0;
+
+ offset = ftell(f);
+ assert_se(offset >= 0);
+
+ for (;;) {
+ _cleanup_free_ char *l = NULL;
+ const char *ll;
+
+ if (read_line(f, LONG_LINE_MAX, &l) <= 0)
+ break;
+
+ ll = startswith(l, UTF8_BYTE_ORDER_MARK) ?: l;
+ ll = ll + strspn(ll, WHITESPACE);
+
+ if (HAS_FEATURE_MEMORY_SANITIZER && startswith(ll, "ListenNetlink")) {
+ /* ListenNetlink causes a false positive in msan,
+ * let's skip this for now. */
+ log_notice("Skipping test because ListenNetlink= is present");
+ return 0;
+ }
+ }
+
+ assert_se(fseek(f, offset, SEEK_SET) == 0);
+
+ /* We don't want to fill the logs with messages about parse errors.
+ * Disable most logging if not running standalone */
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
+
+ assert_se(manager_new(UNIT_FILE_SYSTEM, MANAGER_TEST_RUN_MINIMAL, &m) >= 0);
+
+ name = strjoina("a.", unit_type_to_string(t));
+ assert_se(unit_new_for_name(m, unit_vtable[t]->object_size, name, &u) >= 0);
+
+ (void) config_parse(name, name, f,
+ UNIT_VTABLE(u)->sections,
+ config_item_perf_lookup, load_fragment_gperf_lookup,
+ CONFIG_PARSE_ALLOW_INCLUDE, u);
+
+ g = open_memstream(&out, &out_size);
+ assert_se(g);
+
+ unit_dump(u, g, "");
+
+ return 0;
+}
diff --git a/src/fuzz/fuzz.h b/src/fuzz/fuzz.h
index 5293c5762f..e2bfab3168 100644
--- a/src/fuzz/fuzz.h
+++ b/src/fuzz/fuzz.h
@@ -1,20 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright 2018 Jonathan Rudenberg
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
#include <stdint.h>
diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build
index 09a8c8a11d..ad44778889 100644
--- a/src/fuzz/meson.build
+++ b/src/fuzz/meson.build
@@ -1,18 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-# Copyright 2018 Jonathan Rudenberg
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
fuzzers += [
[['src/fuzz/fuzz-dns-packet.c',
@@ -22,9 +8,19 @@ fuzzers += [
[libgcrypt,
libgpg_error,
libm]],
- [['src/fuzz/fuzz-dhcp-server.c',
- ],
+
+ [['src/fuzz/fuzz-dhcp-server.c'],
[libsystemd_network,
libshared],
- []]
+ []],
+
+ [['src/fuzz/fuzz-unit-file.c'],
+ [libcore,
+ libshared],
+ [libmount]],
+
+ [['src/fuzz/fuzz-journal-remote.c'],
+ [libsystemd_journal_remote,
+ libshared],
+ []],
]
diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c
index f475aef66c..6af4c39137 100644
--- a/src/getty-generator/getty-generator.c
+++ b/src/getty-generator/getty-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index cbdbc5afe2..f72a55c20a 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <blkid.h>
#include <stdlib.h>
@@ -59,9 +41,9 @@ static bool arg_root_enabled = true;
static bool arg_root_rw = false;
static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
- _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
+ _cleanup_free_ char *e = NULL, *n = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
- char *ret;
+ const char *p;
int r;
assert(id);
@@ -87,10 +69,7 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
if (!what_escaped)
return log_oom();
- p = strjoin(arg_dest, "/", n);
- if (!p)
- return log_oom();
-
+ p = strjoina(arg_dest, "/", n);
f = fopen(p, "wxe");
if (!f)
return log_error_errno(errno, "Failed to create unit file %s: %m", p);
@@ -138,11 +117,7 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
return r;
}
- free(p);
- p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf");
- if (!p)
- return log_oom();
-
+ p = strjoina(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf");
mkdir_parents_label(p, 0755);
r = write_string_file(p,
"# Automatically generated by systemd-gpt-auto-generator\n\n"
@@ -152,12 +127,16 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
if (r < 0)
return log_error_errno(r, "Failed to write device drop-in: %m");
- ret = strappend("/dev/mapper/", id);
- if (!ret)
- return log_oom();
+ if (device) {
+ char *ret;
+
+ ret = strappend("/dev/mapper/", id);
+ if (!ret)
+ return log_oom();
- if (device)
*device = ret;
+ }
+
return 0;
}
@@ -246,7 +225,7 @@ static int add_mount(
return 0;
}
-static bool path_is_busy(const char *where) {
+static int path_is_busy(const char *where) {
int r;
/* already a mountpoint; generators run during reload */
@@ -259,13 +238,17 @@ static bool path_is_busy(const char *where) {
return false;
if (r < 0)
- return true;
+ return log_warning_errno(r, "Cannot check if \"%s\" is a mount point: %m", where);
/* not a mountpoint but it contains files */
- if (dir_is_empty(where) <= 0)
- return true;
+ r = dir_is_empty(where);
+ if (r < 0)
+ return log_warning_errno(r, "Cannot check if \"%s\" is empty: %m", where);
+ if (r > 0)
+ return false;
- return false;
+ log_debug("\"%s\" already populated, ignoring.", where);
+ return true;
}
static int add_partition_mount(
@@ -274,12 +257,12 @@ static int add_partition_mount(
const char *where,
const char *description) {
+ int r;
assert(p);
- if (path_is_busy(where)) {
- log_debug("%s already populated, ignoring.", where);
- return 0;
- }
+ r = path_is_busy(where);
+ if (r != 0)
+ return r < 0 ? r : 0;
return add_mount(
id,
@@ -350,8 +333,8 @@ static int add_automount(
usec_t timeout) {
_cleanup_free_ char *unit = NULL;
- _cleanup_free_ char *opt, *p = NULL;
_cleanup_fclose_ FILE *f = NULL;
+ const char *opt = "noauto", *p;
int r;
assert(id);
@@ -359,11 +342,7 @@ static int add_automount(
assert(description);
if (options)
- opt = strjoin(options, ",noauto");
- else
- opt = strdup("noauto");
- if (!opt)
- return log_oom();
+ opt = strjoina(options, ",", opt);
r = add_mount(id,
what,
@@ -380,10 +359,7 @@ static int add_automount(
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
- p = strjoin(arg_dest, "/", unit);
- if (!p)
- return log_oom();
-
+ p = strjoina(arg_dest, "/", unit);
f = fopen(p, "wxe");
if (!f)
return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
@@ -430,10 +406,9 @@ static int add_esp(DissectedPartition *p) {
return 0;
}
- if (path_is_busy(esp)) {
- log_debug("%s already populated, ignoring.", esp);
- return 0;
- }
+ r = path_is_busy(esp);
+ if (r != 0)
+ return r < 0 ? r : 0;
if (is_efi_boot()) {
sd_id128_t loader_uuid;
@@ -471,8 +446,8 @@ static int add_esp(DissectedPartition *p) {
#endif
static int open_parent(dev_t devnum, int *ret) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
const char *name, *devtype, *node;
struct udev_device *parent;
dev_t pn;
diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c
index a81386ef63..4b79e3def4 100644
--- a/src/hibernate-resume/hibernate-resume-generator.c
+++ b/src/hibernate-resume/hibernate-resume-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Ivan Shapovalov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c
index 2a427210cd..397757fa46 100644
--- a/src/hibernate-resume/hibernate-resume.c
+++ b/src/hibernate-resume/hibernate-resume.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Ivan Shapovalov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
index e06b111b43..8587f5c59f 100644
--- a/src/hostname/hostnamectl.c
+++ b/src/hostname/hostnamectl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
#include <locale.h>
@@ -33,7 +15,9 @@
#include "bus-util.h"
#include "hostname-util.h"
#include "spawn-polkit-agent.h"
+#include "terminal-util.h"
#include "util.h"
+#include "verbs.h"
static bool arg_ask_password = true;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
@@ -43,19 +27,20 @@ static bool arg_pretty = false;
static bool arg_static = false;
typedef struct StatusInfo {
- char *hostname;
- char *static_hostname;
- char *pretty_hostname;
- char *icon_name;
- char *chassis;
- char *deployment;
- char *location;
- char *kernel_name;
- char *kernel_release;
- char *os_pretty_name;
- char *os_cpe_name;
- char *virtualization;
- char *architecture;
+ const char *hostname;
+ const char *static_hostname;
+ const char *pretty_hostname;
+ const char *icon_name;
+ const char *chassis;
+ const char *deployment;
+ const char *location;
+ const char *kernel_name;
+ const char *kernel_release;
+ const char *os_pretty_name;
+ const char *os_cpe_name;
+ const char *virtualization;
+ const char *architecture;
+ const char *home_url;
} StatusInfo;
static void print_status_info(StatusInfo *i) {
@@ -99,8 +84,17 @@ static void print_status_info(StatusInfo *i) {
if (!isempty(i->virtualization))
printf(" Virtualization: %s\n", i->virtualization);
- if (!isempty(i->os_pretty_name))
- printf(" Operating System: %s\n", i->os_pretty_name);
+ if (!isempty(i->os_pretty_name)) {
+ _cleanup_free_ char *formatted = NULL;
+ const char *t = i->os_pretty_name;
+
+ if (i->home_url) {
+ if (terminal_urlify(i->home_url, i->os_pretty_name, &formatted) >= 0)
+ t = formatted;
+ }
+
+ printf(" Operating System: %s\n", t);
+ }
if (!isempty(i->os_cpe_name))
printf(" CPE OS Name: %s\n", i->os_cpe_name);
@@ -153,6 +147,7 @@ static int show_all_names(sd_bus *bus, sd_bus_error *error) {
{ "KernelRelease", "s", NULL, offsetof(StatusInfo, kernel_release) },
{ "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name) },
{ "OperatingSystemCPEName", "s", NULL, offsetof(StatusInfo, os_cpe_name) },
+ { "HomeURL", "s", NULL, offsetof(StatusInfo, home_url) },
{}
};
@@ -162,49 +157,38 @@ static int show_all_names(sd_bus *bus, sd_bus_error *error) {
{}
};
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *host_message = NULL, *manager_message = NULL;
int r;
r = bus_map_all_properties(bus,
"org.freedesktop.hostname1",
"/org/freedesktop/hostname1",
hostname_map,
+ 0,
error,
+ &host_message,
&info);
if (r < 0)
- goto fail;
+ return r;
- bus_map_all_properties(bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- manager_map,
- error,
- &info);
+ r = bus_map_all_properties(bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ manager_map,
+ 0,
+ error,
+ &manager_message,
+ &info);
print_status_info(&info);
-fail:
- free(info.hostname);
- free(info.static_hostname);
- free(info.pretty_hostname);
- free(info.icon_name);
- free(info.chassis);
- free(info.deployment);
- free(info.location);
- free(info.kernel_name);
- free(info.kernel_release);
- free(info.os_pretty_name);
- free(info.os_cpe_name);
- free(info.virtualization);
- free(info.architecture);
-
return r;
}
-static int show_status(sd_bus *bus, char **args, unsigned n) {
+static int show_status(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
int r;
- assert(args);
-
if (arg_pretty || arg_static || arg_transient) {
const char *attr;
@@ -247,14 +231,12 @@ static int set_simple_string(sd_bus *bus, const char *method, const char *value)
return r;
}
-static int set_hostname(sd_bus *bus, char **args, unsigned n) {
+static int set_hostname(int argc, char **argv, void *userdata) {
_cleanup_free_ char *h = NULL;
- const char *hostname = args[1];
+ const char *hostname = argv[1];
+ sd_bus *bus = userdata;
int r;
- assert(args);
- assert(n == 2);
-
if (!arg_pretty && !arg_static && !arg_transient)
arg_pretty = arg_static = arg_transient = true;
@@ -301,35 +283,23 @@ static int set_hostname(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int set_icon_name(sd_bus *bus, char **args, unsigned n) {
- assert(args);
- assert(n == 2);
-
- return set_simple_string(bus, "SetIconName", args[1]);
+static int set_icon_name(int argc, char **argv, void *userdata) {
+ return set_simple_string(userdata, "SetIconName", argv[1]);
}
-static int set_chassis(sd_bus *bus, char **args, unsigned n) {
- assert(args);
- assert(n == 2);
-
- return set_simple_string(bus, "SetChassis", args[1]);
+static int set_chassis(int argc, char **argv, void *userdata) {
+ return set_simple_string(userdata, "SetChassis", argv[1]);
}
-static int set_deployment(sd_bus *bus, char **args, unsigned n) {
- assert(args);
- assert(n == 2);
-
- return set_simple_string(bus, "SetDeployment", args[1]);
+static int set_deployment(int argc, char **argv, void *userdata) {
+ return set_simple_string(userdata, "SetDeployment", argv[1]);
}
-static int set_location(sd_bus *bus, char **args, unsigned n) {
- assert(args);
- assert(n == 2);
-
- return set_simple_string(bus, "SetLocation", args[1]);
+static int set_location(int argc, char **argv, void *userdata) {
+ return set_simple_string(userdata, "SetLocation", argv[1]);
}
-static void help(void) {
+static int help(void) {
printf("%s [OPTIONS...] COMMAND ...\n\n"
"Query or change system hostname.\n\n"
" -h --help Show this help\n"
@@ -348,6 +318,12 @@ static void help(void) {
" set-deployment NAME Set deployment environment for host\n"
" set-location NAME Set location for host\n"
, program_invocation_short_name);
+
+ return 0;
+}
+
+static int verb_help(int argc, char **argv, void *userdata) {
+ return help();
}
static int parse_argv(int argc, char *argv[]) {
@@ -382,8 +358,7 @@ static int parse_argv(int argc, char *argv[]) {
switch (c) {
case 'h':
- help();
- return 0;
+ return help();
case ARG_VERSION:
return version();
@@ -426,82 +401,18 @@ static int parse_argv(int argc, char *argv[]) {
static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) {
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-hostname", EQUAL, 2, set_hostname },
- { "set-icon-name", EQUAL, 2, set_icon_name },
- { "set-chassis", EQUAL, 2, set_chassis },
- { "set-deployment", EQUAL, 2, set_deployment },
- { "set-location", EQUAL, 2, set_location },
+ static const Verb verbs[] = {
+ { "status", VERB_ANY, 1, VERB_DEFAULT, show_status },
+ { "set-hostname", 2, 2, 0, set_hostname },
+ { "set-icon-name", 2, 2, 0, set_icon_name },
+ { "set-chassis", 2, 2, 0, set_chassis },
+ { "set-deployment", 2, 2, 0, set_deployment },
+ { "set-location", 2, 2, 0, set_location },
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */
+ {}
};
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
+ return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char *argv[]) {
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index 1c8c76934c..ee51002ece 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -29,6 +11,7 @@
#include "env-util.h"
#include "fileio-label.h"
#include "hostname-util.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "selinux-util.h"
@@ -52,6 +35,7 @@ enum {
PROP_KERNEL_VERSION,
PROP_OS_PRETTY_NAME,
PROP_OS_CPE_NAME,
+ PROP_HOME_URL,
_PROP_MAX
};
@@ -100,7 +84,7 @@ static int context_read_data(Context *c) {
if (r < 0 && r != -ENOENT)
return r;
- r = parse_env_file("/etc/machine-info", NEWLINE,
+ r = parse_env_file(NULL, "/etc/machine-info", NEWLINE,
"PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME],
"ICON_NAME", &c->data[PROP_ICON_NAME],
"CHASSIS", &c->data[PROP_CHASSIS],
@@ -110,16 +94,11 @@ static int context_read_data(Context *c) {
if (r < 0 && r != -ENOENT)
return r;
- r = parse_env_file("/etc/os-release", NEWLINE,
- "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
- "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
- NULL);
- if (r == -ENOENT)
- r = parse_env_file("/usr/lib/os-release", NEWLINE,
- "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
- "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
- NULL);
-
+ r = parse_os_release(NULL,
+ "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
+ "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
+ "HOME_URL", &c->data[PROP_HOME_URL],
+ NULL);
if (r < 0 && r != -ENOENT)
return r;
@@ -261,7 +240,6 @@ static char* context_fallback_icon_name(Context *c) {
return strdup("computer");
}
-
static bool hostname_is_useful(const char *hn) {
return !isempty(hn) && !is_localhost(hn);
}
@@ -349,8 +327,7 @@ static int context_write_data_machine_info(Context *c) {
if (!u)
return -ENOMEM;
- strv_free(l);
- l = u;
+ strv_free_and_replace(l, u);
}
if (strv_isempty(l)) {
@@ -411,7 +388,6 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
Context *c = userdata;
const char *name;
int interactive;
- char *h;
int r;
assert(m);
@@ -447,12 +423,9 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- h = strdup(name);
- if (!h)
- return -ENOMEM;
-
- free(c->data[PROP_HOSTNAME]);
- c->data[PROP_HOSTNAME] = h;
+ r = free_and_strdup(&c->data[PROP_HOSTNAME], name);
+ if (r < 0)
+ return r;
r = context_update_kernel_hostname(c);
if (r < 0) {
@@ -485,6 +458,9 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
return sd_bus_reply_method_return(m, NULL);
+ if (!isempty(name) && !hostname_is_valid(name, false))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
+
r = bus_verify_polkit_async(
m,
CAP_SYS_ADMIN,
@@ -499,21 +475,9 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- if (isempty(name))
- c->data[PROP_STATIC_HOSTNAME] = mfree(c->data[PROP_STATIC_HOSTNAME]);
- else {
- char *h;
-
- if (!hostname_is_valid(name, false))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
-
- h = strdup(name);
- if (!h)
- return -ENOMEM;
-
- free(c->data[PROP_STATIC_HOSTNAME]);
- c->data[PROP_STATIC_HOSTNAME] = h;
- }
+ r = free_and_strdup(&c->data[PROP_STATIC_HOSTNAME], name);
+ if (r < 0)
+ return r;
r = context_update_kernel_hostname(c);
if (r < 0) {
@@ -551,6 +515,22 @@ static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_mess
if (streq_ptr(name, c->data[prop]))
return sd_bus_reply_method_return(m, NULL);
+ if (!isempty(name)) {
+ /* The icon name might ultimately be used as file
+ * name, so better be safe than sorry */
+
+ if (prop == PROP_ICON_NAME && !filename_is_valid(name))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
+ if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name);
+ if (prop == PROP_CHASSIS && !valid_chassis(name))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
+ if (prop == PROP_DEPLOYMENT && !valid_deployment(name))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name);
+ if (prop == PROP_LOCATION && string_has_cc(name, NULL))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);
+ }
+
/* Since the pretty hostname should always be changed at the
* same time as the static one, use the same policy action for
* both... */
@@ -569,32 +549,9 @@ static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_mess
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- if (isempty(name))
- c->data[prop] = mfree(c->data[prop]);
- else {
- char *h;
-
- /* The icon name might ultimately be used as file
- * name, so better be safe than sorry */
-
- if (prop == PROP_ICON_NAME && !filename_is_valid(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
- if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name);
- if (prop == PROP_CHASSIS && !valid_chassis(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
- if (prop == PROP_DEPLOYMENT && !valid_deployment(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name);
- if (prop == PROP_LOCATION && string_has_cc(name, NULL))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);
-
- h = strdup(name);
- if (!h)
- return -ENOMEM;
-
- free(c->data[prop]);
- c->data[prop] = h;
- }
+ r = free_and_strdup(&c->data[prop], name);
+ if (r < 0)
+ return r;
r = context_write_data_machine_info(c);
if (r < 0) {
@@ -654,6 +611,7 @@ static const sd_bus_vtable hostname_vtable[] = {
SD_BUS_PROPERTY("KernelVersion", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_VERSION, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_OS_PRETTY_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OperatingSystemCPEName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_OS_CPE_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("HomeURL", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_HOME_URL, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("SetHostname", "sb", NULL, method_set_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetStaticHostname", "sb", NULL, method_set_static_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetPrettyHostname", "sb", NULL, method_set_pretty_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -688,8 +646,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
- *_bus = bus;
- bus = NULL;
+ *_bus = TAKE_PTR(bus);
return 0;
}
diff --git a/src/hostname/meson.build b/src/hostname/meson.build
index 1ab9271b4c..db66ba5531 100644
--- a/src/hostname/meson.build
+++ b/src/hostname/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
if conf.get('ENABLE_HOSTNAMED') == 1
install_data('org.freedesktop.hostname1.conf',
diff --git a/src/hostname/org.freedesktop.hostname1.policy b/src/hostname/org.freedesktop.hostname1.policy
index 4ac82c659c..e1519ce86b 100644
--- a/src/hostname/org.freedesktop.hostname1.policy
+++ b/src/hostname/org.freedesktop.hostname1.policy
@@ -5,8 +5,6 @@
<!--
SPDX-License-Identifier: LGPL-2.1+
- 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
diff --git a/src/hostname/org.freedesktop.hostname1.service b/src/hostname/org.freedesktop.hostname1.service
index 421a8c607b..98c7bcbd84 100644
--- a/src/hostname/org.freedesktop.hostname1.service
+++ b/src/hostname/org.freedesktop.hostname1.service
@@ -1,7 +1,5 @@
# SPDX-License-Identifier: LGPL-2.1+
#
-# This file is part of systemd.
-#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index f27f60e977..317cad8a67 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <ctype.h>
#include <getopt.h>
@@ -47,6 +29,7 @@
static const char *arg_hwdb_bin_dir = "/etc/udev";
static const char *arg_root = "";
+static bool arg_strict;
static const char * const conf_file_dirs[] = {
"/etc/udev/hwdb.d",
@@ -123,7 +106,7 @@ static struct trie_node *node_lookup(const struct trie_node *node, uint8_t c) {
struct trie_child_entry search;
search.c = c;
- child = bsearch(&search, node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp);
+ child = bsearch_safe(&search, node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp);
if (child)
return child->child;
return NULL;
@@ -502,7 +485,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
_cleanup_strv_free_ char **match_list = NULL;
uint32_t line_number = 0;
char *match = NULL;
- int r;
+ int r = 0, err;
f = fopen(filename, "re");
if (!f)
@@ -537,6 +520,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (line[0] == ' ') {
log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Match expected but got indented property \"%s\", ignoring line", line);
+ r = -EINVAL;
break;
}
@@ -547,9 +531,9 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (!match)
return -ENOMEM;
- r = strv_consume(&match_list, match);
- if (r < 0)
- return r;
+ err = strv_consume(&match_list, match);
+ if (err < 0)
+ return err;
break;
@@ -557,7 +541,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (len == 0) {
log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Property expected, ignoring record with no properties");
-
+ r = -EINVAL;
state = HW_NONE;
strv_clear(match_list);
break;
@@ -569,16 +553,18 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (!match)
return -ENOMEM;
- r = strv_consume(&match_list, match);
- if (r < 0)
- return r;
+ err = strv_consume(&match_list, match);
+ if (err < 0)
+ return err;
break;
}
/* first data */
state = HW_DATA;
- insert_data(trie, match_list, line, filename, file_priority, line_number);
+ err = insert_data(trie, match_list, line, filename, file_priority, line_number);
+ if (err < 0)
+ r = err;
break;
case HW_DATA:
@@ -592,12 +578,15 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
if (line[0] != ' ') {
log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Property or empty line expected, got \"%s\", ignoring record", line);
+ r = -EINVAL;
state = HW_NONE;
strv_clear(match_list);
break;
}
- insert_data(trie, match_list, line, filename, file_priority, line_number);
+ err = insert_data(trie, match_list, line, filename, file_priority, line_number);
+ if (err < 0)
+ r = err;
break;
};
}
@@ -606,7 +595,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Property expected, ignoring record with no properties");
- return 0;
+ return r;
}
static int hwdb_query(int argc, char *argv[], void *userdata) {
@@ -636,7 +625,7 @@ static int hwdb_update(int argc, char *argv[], void *userdata) {
_cleanup_strv_free_ char **files = NULL;
char **f;
uint16_t file_priority = 1;
- int r;
+ int r = 0, err;
trie = new0(struct trie, 1);
if (!trie)
@@ -654,13 +643,15 @@ static int hwdb_update(int argc, char *argv[], void *userdata) {
trie->nodes_count++;
- r = conf_files_list_strv(&files, ".hwdb", arg_root, 0, conf_file_dirs);
- if (r < 0)
- return log_error_errno(r, "Failed to enumerate hwdb files: %m");
+ err = conf_files_list_strv(&files, ".hwdb", arg_root, 0, conf_file_dirs);
+ if (err < 0)
+ return log_error_errno(err, "Failed to enumerate hwdb files: %m");
STRV_FOREACH(f, files) {
log_debug("Reading file \"%s\"", *f);
- import_file(trie, *f, file_priority++);
+ err = import_file(trie, *f, file_priority++);
+ if (err < 0 && arg_strict)
+ r = err;
}
strbuf_complete(trie->strings);
@@ -684,23 +675,28 @@ static int hwdb_update(int argc, char *argv[], void *userdata) {
return -ENOMEM;
mkdir_parents_label(hwdb_bin, 0755);
- r = trie_store(trie, hwdb_bin);
- if (r < 0)
- return log_error_errno(r, "Failure writing database %s: %m", hwdb_bin);
+ err = trie_store(trie, hwdb_bin);
+ if (err < 0)
+ return log_error_errno(err, "Failure writing database %s: %m", hwdb_bin);
- return label_fix(hwdb_bin, false, false);
+ err = label_fix(hwdb_bin, 0);
+ if (err < 0)
+ return err;
+
+ return r;
}
static void help(void) {
printf("Usage: %s OPTIONS COMMAND\n\n"
"Update or query the hardware database.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n"
- " -r --root=PATH Alternative root path in the filesystem\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " -s --strict When updating, return non-zero exit value on any parsing error\n"
+ " --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n"
+ " -r --root=PATH Alternative root path in the filesystem\n\n"
"Commands:\n"
- " update Update the hwdb database\n"
- " query MODALIAS Query database and print result\n",
+ " update Update the hwdb database\n"
+ " query MODALIAS Query database and print result\n",
program_invocation_short_name);
}
@@ -714,6 +710,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "usr", no_argument, NULL, ARG_USR },
+ { "strict", no_argument, NULL, 's' },
{ "root", required_argument, NULL, 'r' },
{}
};
@@ -723,7 +720,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "ut:r:h", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "ust:r:h", options, NULL)) >= 0) {
switch(c) {
case 'h':
@@ -737,6 +734,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_hwdb_bin_dir = UDEVLIBEXECDIR;
break;
+ case 's':
+ arg_strict = true;
+ break;
+
case 'r':
arg_root = optarg;
break;
@@ -753,7 +754,7 @@ static int parse_argv(int argc, char *argv[]) {
}
static int hwdb_main(int argc, char *argv[]) {
- const Verb verbs[] = {
+ static const Verb verbs[] = {
{ "update", 1, 1, 0, hwdb_update },
{ "query", 2, 2, 0, hwdb_query },
{},
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index 62bbaa500d..b85462176d 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "curl-util.h"
@@ -50,7 +32,7 @@ static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *u
translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd)));
- if ((revents & (EPOLLIN|EPOLLOUT)) == (EPOLLIN|EPOLLOUT))
+ if (FLAGS_SET(revents, EPOLLIN | EPOLLOUT))
action = CURL_POLL_INOUT;
else if (revents & EPOLLIN)
action = CURL_POLL_IN;
@@ -272,8 +254,7 @@ int curl_glue_new(CurlGlue **glue, sd_event *event) {
if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK)
return -EINVAL;
- *glue = g;
- g = NULL;
+ *glue = TAKE_PTR(g);
return 0;
}
@@ -379,19 +360,14 @@ struct curl_slist *curl_slist_new(const char *first, ...) {
}
int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value) {
- const char *p = contents;
- size_t l;
+ const char *p;
char *s;
- l = strlen(field);
- if (sz < l)
- return 0;
-
- if (memcmp(p, field, l) != 0)
+ p = memory_startswith(contents, sz, field);
+ if (!p)
return 0;
- p += l;
- sz -= l;
+ sz -= p - (const char*) contents;
if (memchr(p, 0, sz))
return 0;
diff --git a/src/import/curl-util.h b/src/import/curl-util.h
index c7c24c9f7e..6626eefc56 100644
--- a/src/import/curl-util.h
+++ b/src/import/curl-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <curl/curl.h>
#include <sys/types.h>
diff --git a/src/import/export-raw.c b/src/import/export-raw.c
index eaa6d10915..f97ae461c5 100644
--- a/src/import/export-raw.c
+++ b/src/import/export-raw.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/sendfile.h>
@@ -122,8 +104,7 @@ int raw_export_new(
return r;
}
- *ret = e;
- e = NULL;
+ *ret = TAKE_PTR(e);
return 0;
}
@@ -140,7 +121,7 @@ static void raw_export_report_progress(RawExport *e) {
if (percent == e->last_percent)
return;
- if (!ratelimit_test(&e->progress_rate_limit))
+ if (!ratelimit_below(&e->progress_rate_limit))
return;
sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
@@ -326,13 +307,10 @@ int raw_export_start(RawExport *e, const char *path, int fd, ImportCompressType
/* Try to take a reflink snapshot of the file, if we can t make the export atomic */
tfd = reflink_snapshot(sfd, path);
- if (tfd >= 0) {
- e->input_fd = tfd;
- tfd = -1;
- } else {
- e->input_fd = sfd;
- sfd = -1;
- }
+ if (tfd >= 0)
+ e->input_fd = TAKE_FD(tfd);
+ else
+ e->input_fd = TAKE_FD(sfd);
r = import_compress_init(&e->compress, compress);
if (r < 0)
diff --git a/src/import/export-raw.h b/src/import/export-raw.h
index f932a37955..196b8ef28f 100644
--- a/src/import/export-raw.h
+++ b/src/import/export-raw.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-event.h"
#include "import-compress.h"
diff --git a/src/import/export-tar.c b/src/import/export-tar.c
index dafe3e1c88..9e7c0eaa9d 100644
--- a/src/import/export-tar.c
+++ b/src/import/export-tar.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-daemon.h"
@@ -126,8 +108,7 @@ int tar_export_new(
return r;
}
- *ret = e;
- e = NULL;
+ *ret = TAKE_PTR(e);
return 0;
}
@@ -148,7 +129,7 @@ static void tar_export_report_progress(TarExport *e) {
if (percent == e->last_percent)
return;
- if (!ratelimit_test(&e->progress_rate_limit))
+ if (!ratelimit_below(&e->progress_rate_limit))
return;
sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
diff --git a/src/import/export-tar.h b/src/import/export-tar.h
index 5739ade09a..6abb7d383a 100644
--- a/src/import/export-tar.h
+++ b/src/import/export-tar.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-event.h"
#include "import-compress.h"
diff --git a/src/import/export.c b/src/import/export.c
index 0f32b90051..03eb3e40b2 100644
--- a/src/import/export.c
+++ b/src/import/export.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
@@ -82,13 +64,11 @@ static int export_tar(int argc, char *argv[], void *userdata) {
int r, fd;
if (machine_name_is_valid(argv[1])) {
- r = image_find(argv[1], &image);
+ r = image_find(IMAGE_MACHINE, argv[1], &image);
+ if (r == -ENOENT)
+ return log_error_errno(r, "Machine image %s not found.", argv[1]);
if (r < 0)
return log_error_errno(r, "Failed to look for machine %s: %m", argv[1]);
- if (r == 0) {
- log_error("Machine image %s not found.", argv[1]);
- return -ENOENT;
- }
local = image->path;
} else
@@ -161,13 +141,11 @@ static int export_raw(int argc, char *argv[], void *userdata) {
int r, fd;
if (machine_name_is_valid(argv[1])) {
- r = image_find(argv[1], &image);
+ r = image_find(IMAGE_MACHINE, argv[1], &image);
+ if (r == -ENOENT)
+ return log_error_errno(r, "Machine image %s not found.", argv[1]);
if (r < 0)
return log_error_errno(r, "Failed to look for machine %s: %m", argv[1]);
- if (r == 0) {
- log_error("Machine image %s not found.", argv[1]);
- return -ENOENT;
- }
local = image->path;
} else
diff --git a/src/import/import-common.c b/src/import/import-common.c
index a3dc1dde8c..e2de2c2dd0 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sched.h>
#include <sys/prctl.h>
@@ -117,13 +99,9 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
_exit(EXIT_FAILURE);
}
- pipefd[0] = safe_close(pipefd[0]);
- r = pipefd[1];
- pipefd[1] = -1;
-
*ret = pid;
- return r;
+ return TAKE_FD(pipefd[1]);
}
int import_fork_tar_c(const char *path, pid_t *ret) {
@@ -165,11 +143,7 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
_exit(EXIT_FAILURE);
}
- pipefd[1] = safe_close(pipefd[1]);
- r = pipefd[0];
- pipefd[0] = -1;
-
*ret = pid;
- return r;
+ return TAKE_FD(pipefd[0]);
}
diff --git a/src/import/import-common.h b/src/import/import-common.h
index 55ec536406..99ac5fe970 100644
--- a/src/import/import-common.h
+++ b/src/import/import-common.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int import_make_read_only_fd(int fd);
int import_make_read_only(const char *path);
diff --git a/src/import/import-compress.c b/src/import/import-compress.c
index acb47fef14..1cf29e26f1 100644
--- a/src/import/import-compress.c
+++ b/src/import/import-compress.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "import-compress.h"
#include "string-table.h"
diff --git a/src/import/import-compress.h b/src/import/import-compress.h
index 1eac4d403a..6fb87ccdfb 100644
--- a/src/import/import-compress.h
+++ b/src/import/import-compress.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <bzlib.h>
#include <lzma.h>
#include <sys/types.h>
diff --git a/src/import/import-raw.c b/src/import/import-raw.c
index f117c94da2..f31432cd04 100644
--- a/src/import/import-raw.c
+++ b/src/import/import-raw.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/fs.h>
@@ -141,8 +123,7 @@ int raw_import_new(
return r;
}
- *ret = i;
- i = NULL;
+ *ret = TAKE_PTR(i);
return 0;
}
@@ -163,7 +144,7 @@ static void raw_import_report_progress(RawImport *i) {
if (percent == i->last_percent)
return;
- if (!ratelimit_test(&i->progress_rate_limit))
+ if (!ratelimit_below(&i->progress_rate_limit))
return;
sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
@@ -210,8 +191,7 @@ static int raw_import_maybe_convert_qcow2(RawImport *i) {
free_and_replace(i->temp_path, t);
safe_close(i->output_fd);
- i->output_fd = converted_fd;
- converted_fd = -1;
+ i->output_fd = TAKE_FD(converted_fd);
return 1;
}
diff --git a/src/import/import-raw.h b/src/import/import-raw.h
index 1e0227ab55..de4c3ea337 100644
--- a/src/import/import-raw.h
+++ b/src/import/import-raw.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-event.h"
#include "import-util.h"
diff --git a/src/import/import-tar.c b/src/import/import-tar.c
index 09c7654adc..89c95af279 100644
--- a/src/import/import-tar.c
+++ b/src/import/import-tar.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/fs.h>
@@ -148,8 +130,7 @@ int tar_import_new(
return r;
}
- *ret = i;
- i = NULL;
+ *ret = TAKE_PTR(i);
return 0;
}
@@ -170,7 +151,7 @@ static void tar_import_report_progress(TarImport *i) {
if (percent == i->last_percent)
return;
- if (!ratelimit_test(&i->progress_rate_limit))
+ if (!ratelimit_below(&i->progress_rate_limit))
return;
sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
diff --git a/src/import/import-tar.h b/src/import/import-tar.h
index 44743c9cb3..347f522614 100644
--- a/src/import/import-tar.h
+++ b/src/import/import-tar.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-event.h"
#include "import-util.h"
diff --git a/src/import/import.c b/src/import/import.c
index b94b196b87..35c8e6d630 100644
--- a/src/import/import.c
+++ b/src/import/import.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
@@ -88,10 +70,11 @@ static int import_tar(int argc, char *argv[], void *userdata) {
}
if (!arg_force) {
- r = image_find(local, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
- else if (r > 0) {
+ r = image_find(IMAGE_MACHINE, local, NULL);
+ if (r < 0) {
+ if (r != -ENOENT)
+ return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
+ } else {
log_error("Image '%s' already exists.", local);
return -EEXIST;
}
@@ -183,10 +166,11 @@ static int import_raw(int argc, char *argv[], void *userdata) {
}
if (!arg_force) {
- r = image_find(local, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
- else if (r > 0) {
+ r = image_find(IMAGE_MACHINE, local, NULL);
+ if (r < 0) {
+ if (r != -ENOENT)
+ return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
+ } else {
log_error("Image '%s' already exists.", local);
return -EEXIST;
}
diff --git a/src/import/importd.c b/src/import/importd.c
index 10f52c7fc1..04563fb098 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/prctl.h>
#include <sys/wait.h>
@@ -187,8 +169,7 @@ static int transfer_new(Manager *m, Transfer **ret) {
t->manager = m;
t->id = id;
- *ret = t;
- t = NULL;
+ *ret = TAKE_PTR(t);
return 0;
}
@@ -453,8 +434,7 @@ static int transfer_start(Transfer *t) {
}
pipefd[1] = safe_close(pipefd[1]);
- t->log_fd = pipefd[0];
- pipefd[0] = -1;
+ t->log_fd = TAKE_FD(pipefd[0]);
t->stdin_fd = safe_close(t->stdin_fd);
@@ -640,8 +620,7 @@ static int manager_new(Manager **ret) {
if (r < 0)
return r;
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
@@ -1083,8 +1062,7 @@ static int transfer_node_enumerator(sd_bus *bus, const char *path, void *userdat
k++;
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/import/meson.build b/src/import/meson.build
index 975afc624d..283ba08c67 100644
--- a/src/import/meson.build
+++ b/src/import/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
systemd_importd_sources = files('''
importd.c
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index 7651870bf0..4117ed2e6a 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/prctl.h>
@@ -124,8 +106,7 @@ int pull_find_old_etags(
return r;
}
- *etags = l;
- l = NULL;
+ *etags = TAKE_PTR(l);
return 0;
}
@@ -259,8 +240,7 @@ int pull_make_auxiliary_job(
job->on_finished = on_finished;
job->compressed_max = job->uncompressed_max = 1ULL * 1024ULL * 1024ULL;
- *ret = job;
- job = NULL;
+ *ret = TAKE_PTR(job);
return 0;
}
diff --git a/src/import/pull-common.h b/src/import/pull-common.h
index 14c81fb1f1..65f239da2e 100644
--- a/src/import/pull-common.h
+++ b/src/import/pull-common.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "import-util.h"
diff --git a/src/import/pull-job.c b/src/import/pull-job.c
index 2b71766798..89dd20afa3 100644
--- a/src/import/pull-job.c
+++ b/src/import/pull-job.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/xattr.h>
@@ -581,8 +563,7 @@ int pull_job_new(PullJob **ret, const char *url, CurlGlue *glue, void *userdata)
if (!j->url)
return -ENOMEM;
- *ret = j;
- j = NULL;
+ *ret = TAKE_PTR(j);
return 0;
}
diff --git a/src/import/pull-job.h b/src/import/pull-job.h
index e8becdc002..0c104af758 100644
--- a/src/import/pull-job.h
+++ b/src/import/pull-job.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <gcrypt.h>
#include "curl-util.h"
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index 880cb84ba8..e68f197c79 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <curl/curl.h>
#include <linux/fs.h>
@@ -166,8 +148,7 @@ int raw_pull_new(
i->glue->on_finished = pull_job_curl_on_finished;
i->glue->userdata = i;
- *ret = i;
- i = NULL;
+ *ret = TAKE_PTR(i);
return 0;
}
@@ -272,8 +253,7 @@ static int raw_pull_maybe_convert_qcow2(RawPull *i) {
free_and_replace(i->temp_path, t);
safe_close(i->raw_job->disk_fd);
- i->raw_job->disk_fd = converted_fd;
- converted_fd = -1;
+ i->raw_job->disk_fd = TAKE_FD(converted_fd);
return 1;
}
diff --git a/src/import/pull-raw.h b/src/import/pull-raw.h
index c951fc25c1..4ccd65b7e6 100644
--- a/src/import/pull-raw.h
+++ b/src/import/pull-raw.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-event.h"
#include "import-util.h"
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index 6ee63bdad5..56ec252e98 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <curl/curl.h>
#include <sys/prctl.h>
@@ -159,8 +141,7 @@ int tar_pull_new(
i->glue->on_finished = pull_job_curl_on_finished;
i->glue->userdata = i;
- *ret = i;
- i = NULL;
+ *ret = TAKE_PTR(i);
return 0;
}
diff --git a/src/import/pull-tar.h b/src/import/pull-tar.h
index 9f004acdc6..76f920eea9 100644
--- a/src/import/pull-tar.h
+++ b/src/import/pull-tar.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-event.h"
#include "import-util.h"
diff --git a/src/import/pull.c b/src/import/pull.c
index 325f7e3d50..26be5bbf0b 100644
--- a/src/import/pull.c
+++ b/src/import/pull.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
@@ -96,10 +78,11 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
}
if (!arg_force) {
- r = image_find(local, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
- else if (r > 0) {
+ r = image_find(IMAGE_MACHINE, local, NULL);
+ if (r < 0) {
+ if (r != -ENOENT)
+ return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
+ } else {
log_error("Image '%s' already exists.", local);
return -EEXIST;
}
@@ -182,10 +165,11 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
}
if (!arg_force) {
- r = image_find(local, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
- else if (r > 0) {
+ r = image_find(IMAGE_MACHINE, local, NULL);
+ if (r < 0) {
+ if (r != -ENOENT)
+ return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
+ } else {
log_error("Image '%s' already exists.", local);
return -EEXIST;
}
diff --git a/src/import/qcow2-util.c b/src/import/qcow2-util.c
index 7e37bf4026..e927b60fce 100644
--- a/src/import/qcow2-util.c
+++ b/src/import/qcow2-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <zlib.h>
diff --git a/src/import/qcow2-util.h b/src/import/qcow2-util.h
index ae1fb8fd38..7393d9837a 100644
--- a/src/import/qcow2-util.h
+++ b/src/import/qcow2-util.h
@@ -1,24 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int qcow2_detect(int fd);
int qcow2_convert(int qcow2_fd, int raw_fd);
diff --git a/src/import/test-qcow2.c b/src/import/test-qcow2.c
index 428191d18e..bd2b458219 100644
--- a/src/import/test-qcow2.c
+++ b/src/import/test-qcow2.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "fd-util.h"
#include "log.h"
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index c1af13d15b..0c5aab6968 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <ctype.h>
#include <errno.h>
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index 59b980873f..3d0c3aafd7 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <getopt.h>
@@ -37,6 +19,7 @@
#include "log.h"
#include "logs-show.h"
#include "microhttpd-util.h"
+#include "os-util.h"
#include "parse-util.h"
#include "sigbus.h"
#include "util.h"
@@ -226,7 +209,7 @@ static ssize_t request_reader_entries(
return MHD_CONTENT_READER_END_WITH_ERROR;
}
- r = output_journal(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH,
+ r = show_journal_entry(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH,
NULL, NULL, NULL);
if (r < 0) {
log_error_errno(r, "Failed to serialize item: %m");
@@ -790,10 +773,8 @@ static int request_handler_machine(
if (r < 0)
return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m");
- if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT)
- (void) parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL);
-
- get_virtualization(&v);
+ (void) parse_os_release(NULL, "PRETTY_NAME", &os_name, NULL);
+ (void) get_virtualization(&v);
r = asprintf(&json,
"{ \"machine_id\" : \"" SD_ID128_FORMAT_STR "\","
@@ -848,7 +829,6 @@ static int request_handler(
if (!streq(method, "GET"))
return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method.");
-
if (!*connection_cls) {
if (!request_meta(connection_cls))
return respond_oom(connection);
diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
new file mode 100644
index 0000000000..8fda9d1499
--- /dev/null
+++ b/src/journal-remote/journal-remote-main.c
@@ -0,0 +1,1145 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include "sd-daemon.h"
+
+#include "conf-parser.h"
+#include "def.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "journal-remote-write.h"
+#include "journal-remote.h"
+#include "process-util.h"
+#include "signal-util.h"
+#include "socket-util.h"
+#include "stat-util.h"
+#include "string-table.h"
+#include "strv.h"
+
+#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem"
+#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem"
+#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem"
+
+static char* arg_url = NULL;
+static char* arg_getter = NULL;
+static char* arg_listen_raw = NULL;
+static char* arg_listen_http = NULL;
+static char* arg_listen_https = NULL;
+static char** arg_files = NULL;
+static int arg_compress = true;
+static int arg_seal = false;
+static int http_socket = -1, https_socket = -1;
+static char** arg_gnutls_log = NULL;
+
+static JournalWriteSplitMode arg_split_mode = _JOURNAL_WRITE_SPLIT_INVALID;
+static char* arg_output = NULL;
+
+static char *arg_key = NULL;
+static char *arg_cert = NULL;
+static char *arg_trust = NULL;
+static bool arg_trust_all = false;
+
+static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
+ [JOURNAL_WRITE_SPLIT_NONE] = "none",
+ [JOURNAL_WRITE_SPLIT_HOST] = "host",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode);
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
+ journal_write_split_mode,
+ JournalWriteSplitMode,
+ "Failed to parse split mode setting");
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+static int spawn_child(const char* child, char** argv) {
+ pid_t child_pid;
+ int fd[2], r;
+
+ if (pipe(fd) < 0)
+ return log_error_errno(errno, "Failed to create pager pipe: %m");
+
+ r = safe_fork("(remote)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid);
+ if (r < 0) {
+ safe_close_pair(fd);
+ return r;
+ }
+
+ /* In the child */
+ if (r == 0) {
+ safe_close(fd[0]);
+
+ r = rearrange_stdio(STDIN_FILENO, fd[1], STDERR_FILENO);
+ if (r < 0) {
+ log_error_errno(r, "Failed to dup pipe to stdout: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ execvp(child, argv);
+ log_error_errno(errno, "Failed to exec child %s: %m", child);
+ _exit(EXIT_FAILURE);
+ }
+
+ safe_close(fd[1]);
+
+ r = fd_nonblock(fd[0], true);
+ if (r < 0)
+ log_warning_errno(errno, "Failed to set child pipe to non-blocking: %m");
+
+ return fd[0];
+}
+
+static int spawn_curl(const char* url) {
+ char **argv = STRV_MAKE("curl",
+ "-HAccept: application/vnd.fdo.journal",
+ "--silent",
+ "--show-error",
+ url);
+ int r;
+
+ r = spawn_child("curl", argv);
+ if (r < 0)
+ log_error_errno(r, "Failed to spawn curl: %m");
+ return r;
+}
+
+static int spawn_getter(const char *getter) {
+ int r;
+ _cleanup_strv_free_ char **words = NULL;
+
+ assert(getter);
+ r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_QUOTES);
+ if (r < 0)
+ return log_error_errno(r, "Failed to split getter option: %m");
+
+ r = spawn_child(words[0], words);
+ if (r < 0)
+ log_error_errno(r, "Failed to spawn getter %s: %m", getter);
+
+ return r;
+}
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+static int null_timer_event_handler(sd_event_source *s,
+ uint64_t usec,
+ void *userdata);
+static int dispatch_http_event(sd_event_source *event,
+ int fd,
+ uint32_t revents,
+ void *userdata);
+
+static int request_meta(void **connection_cls, int fd, char *hostname) {
+ RemoteSource *source;
+ Writer *writer;
+ int r;
+
+ assert(connection_cls);
+ if (*connection_cls)
+ return 0;
+
+ r = journal_remote_get_writer(journal_remote_server_global, hostname, &writer);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to get writer for source %s: %m",
+ hostname);
+
+ source = source_new(fd, true, hostname, writer);
+ if (!source) {
+ writer_unref(writer);
+ return log_oom();
+ }
+
+ log_debug("Added RemoteSource as connection metadata %p", source);
+
+ *connection_cls = source;
+ return 0;
+}
+
+static void request_meta_free(void *cls,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ enum MHD_RequestTerminationCode toe) {
+ RemoteSource *s;
+
+ assert(connection_cls);
+ s = *connection_cls;
+
+ if (s) {
+ log_debug("Cleaning up connection metadata %p", s);
+ source_free(s);
+ *connection_cls = NULL;
+ }
+}
+
+static int process_http_upload(
+ struct MHD_Connection *connection,
+ const char *upload_data,
+ size_t *upload_data_size,
+ RemoteSource *source) {
+
+ bool finished = false;
+ size_t remaining;
+ int r;
+
+ assert(source);
+
+ log_trace("%s: connection %p, %zu bytes",
+ __func__, connection, *upload_data_size);
+
+ if (*upload_data_size) {
+ log_trace("Received %zu bytes", *upload_data_size);
+
+ r = journal_importer_push_data(&source->importer,
+ upload_data, *upload_data_size);
+ if (r < 0)
+ return mhd_respond_oom(connection);
+
+ *upload_data_size = 0;
+ } else
+ finished = true;
+
+ for (;;) {
+ r = process_source(source,
+ journal_remote_server_global->compress,
+ journal_remote_server_global->seal);
+ if (r == -EAGAIN)
+ break;
+ else if (r < 0) {
+ log_warning("Failed to process data for connection %p", connection);
+ if (r == -E2BIG)
+ return mhd_respondf(connection,
+ r, MHD_HTTP_PAYLOAD_TOO_LARGE,
+ "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes.");
+ else
+ return mhd_respondf(connection,
+ r, MHD_HTTP_UNPROCESSABLE_ENTITY,
+ "Processing failed: %m.");
+ }
+ }
+
+ if (!finished)
+ return MHD_YES;
+
+ /* The upload is finished */
+
+ remaining = journal_importer_bytes_remaining(&source->importer);
+ if (remaining > 0) {
+ log_warning("Premature EOF byte. %zu bytes lost.", remaining);
+ return mhd_respondf(connection,
+ 0, MHD_HTTP_EXPECTATION_FAILED,
+ "Premature EOF. %zu bytes of trailing data not processed.",
+ remaining);
+ }
+
+ return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.");
+};
+
+static int request_handler(
+ void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **connection_cls) {
+
+ const char *header;
+ int r, code, fd;
+ _cleanup_free_ char *hostname = NULL;
+
+ assert(connection);
+ assert(connection_cls);
+ assert(url);
+ assert(method);
+
+ log_trace("Handling a connection %s %s %s", method, url, version);
+
+ if (*connection_cls)
+ return process_http_upload(connection,
+ upload_data, upload_data_size,
+ *connection_cls);
+
+ if (!streq(method, "POST"))
+ return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method.");
+
+ if (!streq(url, "/upload"))
+ return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.");
+
+ header = MHD_lookup_connection_value(connection,
+ MHD_HEADER_KIND, "Content-Type");
+ if (!header || !streq(header, "application/vnd.fdo.journal"))
+ return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
+ "Content-Type: application/vnd.fdo.journal is required.");
+
+ {
+ const union MHD_ConnectionInfo *ci;
+
+ ci = MHD_get_connection_info(connection,
+ MHD_CONNECTION_INFO_CONNECTION_FD);
+ if (!ci) {
+ log_error("MHD_get_connection_info failed: cannot get remote fd");
+ return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
+ "Cannot check remote address.");
+ }
+
+ fd = ci->connect_fd;
+ assert(fd >= 0);
+ }
+
+ if (journal_remote_server_global->check_trust) {
+ r = check_permissions(connection, &code, &hostname);
+ if (r < 0)
+ return code;
+ } else {
+ r = getpeername_pretty(fd, false, &hostname);
+ if (r < 0)
+ return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
+ "Cannot check remote hostname.");
+ }
+
+ assert(hostname);
+
+ r = request_meta(connection_cls, fd, hostname);
+ if (r == -ENOMEM)
+ return respond_oom(connection);
+ else if (r < 0)
+ return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "%m");
+
+ hostname = NULL;
+ return MHD_YES;
+}
+
+static int setup_microhttpd_server(RemoteServer *s,
+ int fd,
+ const char *key,
+ const char *cert,
+ const char *trust) {
+ struct MHD_OptionItem opts[] = {
+ { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
+ { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
+ { MHD_OPTION_LISTEN_SOCKET, fd},
+ { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024},
+ { MHD_OPTION_END},
+ { MHD_OPTION_END},
+ { MHD_OPTION_END},
+ { MHD_OPTION_END},
+ { MHD_OPTION_END}};
+ int opts_pos = 4;
+ int flags =
+ MHD_USE_DEBUG |
+ MHD_USE_DUAL_STACK |
+ MHD_USE_EPOLL |
+ MHD_USE_ITC;
+
+ const union MHD_DaemonInfo *info;
+ int r, epoll_fd;
+ MHDDaemonWrapper *d;
+
+ assert(fd >= 0);
+
+ r = fd_nonblock(fd, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd);
+
+/* MHD_OPTION_STRICT_FOR_CLIENT is introduced in microhttpd 0.9.54,
+ * and MHD_USE_PEDANTIC_CHECKS will be deprecated in future.
+ * If MHD_USE_PEDANTIC_CHECKS is '#define'd, then it is deprecated
+ * and we should use MHD_OPTION_STRICT_FOR_CLIENT. On the other hand,
+ * if MHD_USE_PEDANTIC_CHECKS is not '#define'd, then it is not
+ * deprecated yet and there exists an enum element with the same name.
+ * So we can safely use it. */
+#ifdef MHD_USE_PEDANTIC_CHECKS
+ opts[opts_pos++] = (struct MHD_OptionItem)
+ {MHD_OPTION_STRICT_FOR_CLIENT, 1};
+#else
+ flags |= MHD_USE_PEDANTIC_CHECKS;
+#endif
+
+ if (key) {
+ assert(cert);
+
+ opts[opts_pos++] = (struct MHD_OptionItem)
+ {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key};
+ opts[opts_pos++] = (struct MHD_OptionItem)
+ {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert};
+
+ flags |= MHD_USE_TLS;
+
+ if (trust)
+ opts[opts_pos++] = (struct MHD_OptionItem)
+ {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust};
+ }
+
+ d = new(MHDDaemonWrapper, 1);
+ if (!d)
+ return log_oom();
+
+ d->fd = (uint64_t) fd;
+
+ d->daemon = MHD_start_daemon(flags, 0,
+ NULL, NULL,
+ request_handler, NULL,
+ MHD_OPTION_ARRAY, opts,
+ MHD_OPTION_END);
+ if (!d->daemon) {
+ log_error("Failed to start µhttp daemon");
+ r = -EINVAL;
+ goto error;
+ }
+
+ log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
+ key ? "HTTPS" : "HTTP", fd, d);
+
+ info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
+ if (!info) {
+ log_error("µhttp returned NULL daemon info");
+ r = -EOPNOTSUPP;
+ goto error;
+ }
+
+ epoll_fd = info->listen_fd;
+ if (epoll_fd < 0) {
+ log_error("µhttp epoll fd is invalid");
+ r = -EUCLEAN;
+ goto error;
+ }
+
+ r = sd_event_add_io(s->events, &d->io_event,
+ epoll_fd, EPOLLIN,
+ dispatch_http_event, d);
+ if (r < 0) {
+ log_error_errno(r, "Failed to add event callback: %m");
+ goto error;
+ }
+
+ r = sd_event_source_set_description(d->io_event, "io_event");
+ if (r < 0) {
+ log_error_errno(r, "Failed to set source name: %m");
+ goto error;
+ }
+
+ r = sd_event_add_time(s->events, &d->timer_event,
+ CLOCK_MONOTONIC, (uint64_t) -1, 0,
+ null_timer_event_handler, d);
+ if (r < 0) {
+ log_error_errno(r, "Failed to add timer_event: %m");
+ goto error;
+ }
+
+ r = sd_event_source_set_description(d->timer_event, "timer_event");
+ if (r < 0) {
+ log_error_errno(r, "Failed to set source name: %m");
+ goto error;
+ }
+
+ r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops);
+ if (r < 0) {
+ log_oom();
+ goto error;
+ }
+
+ r = hashmap_put(s->daemons, &d->fd, d);
+ if (r < 0) {
+ log_error_errno(r, "Failed to add daemon to hashmap: %m");
+ goto error;
+ }
+
+ s->active++;
+ return 0;
+
+error:
+ MHD_stop_daemon(d->daemon);
+ free(d->daemon);
+ free(d);
+ return r;
+}
+
+static int setup_microhttpd_socket(RemoteServer *s,
+ const char *address,
+ const char *key,
+ const char *cert,
+ const char *trust) {
+ int fd;
+
+ fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM, SOCK_CLOEXEC);
+ if (fd < 0)
+ return fd;
+
+ return setup_microhttpd_server(s, fd, key, cert, trust);
+}
+
+static int null_timer_event_handler(sd_event_source *timer_event,
+ uint64_t usec,
+ void *userdata) {
+ return dispatch_http_event(timer_event, 0, 0, userdata);
+}
+
+static int dispatch_http_event(sd_event_source *event,
+ int fd,
+ uint32_t revents,
+ void *userdata) {
+ MHDDaemonWrapper *d = userdata;
+ int r;
+ MHD_UNSIGNED_LONG_LONG timeout = ULONG_LONG_MAX;
+
+ assert(d);
+
+ r = MHD_run(d->daemon);
+ if (r == MHD_NO) {
+ log_error("MHD_run failed!");
+ // XXX: unregister daemon
+ return -EINVAL;
+ }
+ if (MHD_get_timeout(d->daemon, &timeout) == MHD_NO)
+ timeout = ULONG_LONG_MAX;
+
+ r = sd_event_source_set_time(d->timer_event, timeout);
+ if (r < 0) {
+ log_warning_errno(r, "Unable to set event loop timeout: %m, this may result in indefinite blocking!");
+ return 1;
+ }
+
+ r = sd_event_source_set_enabled(d->timer_event, SD_EVENT_ON);
+ if (r < 0)
+ log_warning_errno(r, "Unable to enable timer_event: %m, this may result in indefinite blocking!");
+
+ return 1; /* work to do */
+}
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+static int setup_signals(RemoteServer *s) {
+ int r;
+
+ assert(s);
+
+ assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0);
+
+ r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s);
+ if (r < 0)
+ return r;
+
+ r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, NULL, s);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int setup_raw_socket(RemoteServer *s, const char *address) {
+ int fd;
+
+ fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM, SOCK_CLOEXEC);
+ if (fd < 0)
+ return fd;
+
+ return journal_remote_add_raw_socket(s, fd);
+}
+
+static int create_remoteserver(
+ RemoteServer *s,
+ const char* key,
+ const char* cert,
+ const char* trust) {
+
+ int r, n, fd;
+ char **file;
+
+ r = journal_remote_server_init(s, arg_output, arg_split_mode, arg_compress, arg_seal);
+ if (r < 0)
+ return r;
+
+ setup_signals(s);
+
+ n = sd_listen_fds(true);
+ if (n < 0)
+ return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
+ else
+ log_debug("Received %d descriptors", n);
+
+ if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) {
+ log_error("Received fewer sockets than expected");
+ return -EBADFD;
+ }
+
+ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
+ if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
+ log_debug("Received a listening socket (fd:%d)", fd);
+
+ if (fd == http_socket)
+ r = setup_microhttpd_server(s, fd, NULL, NULL, NULL);
+ else if (fd == https_socket)
+ r = setup_microhttpd_server(s, fd, key, cert, trust);
+ else
+ r = journal_remote_add_raw_socket(s, fd);
+ } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
+ char *hostname;
+
+ r = getpeername_pretty(fd, false, &hostname);
+ if (r < 0)
+ return log_error_errno(r, "Failed to retrieve remote name: %m");
+
+ log_debug("Received a connection socket (fd:%d) from %s", fd, hostname);
+
+ r = journal_remote_add_source(s, fd, hostname, true);
+ } else {
+ log_error("Unknown socket passed on fd:%d", fd);
+
+ return -EINVAL;
+ }
+
+ if (r < 0)
+ return log_error_errno(r, "Failed to register socket (fd:%d): %m",
+ fd);
+ }
+
+ if (arg_getter) {
+ log_info("Spawning getter %s...", arg_getter);
+ fd = spawn_getter(arg_getter);
+ if (fd < 0)
+ return fd;
+
+ r = journal_remote_add_source(s, fd, (char*) arg_output, false);
+ if (r < 0)
+ return r;
+ }
+
+ if (arg_url) {
+ const char *url;
+ char *hostname, *p;
+
+ if (!strstr(arg_url, "/entries")) {
+ if (endswith(arg_url, "/"))
+ url = strjoina(arg_url, "entries");
+ else
+ url = strjoina(arg_url, "/entries");
+ }
+ else
+ url = strdupa(arg_url);
+
+ log_info("Spawning curl %s...", url);
+ fd = spawn_curl(url);
+ if (fd < 0)
+ return fd;
+
+ hostname =
+ startswith(arg_url, "https://") ?:
+ startswith(arg_url, "http://") ?:
+ arg_url;
+
+ hostname = strdupa(hostname);
+ if ((p = strchr(hostname, '/')))
+ *p = '\0';
+ if ((p = strchr(hostname, ':')))
+ *p = '\0';
+
+ r = journal_remote_add_source(s, fd, hostname, false);
+ if (r < 0)
+ return r;
+ }
+
+ if (arg_listen_raw) {
+ log_debug("Listening on a socket...");
+ r = setup_raw_socket(s, arg_listen_raw);
+ if (r < 0)
+ return r;
+ }
+
+ if (arg_listen_http) {
+ r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ if (arg_listen_https) {
+ r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust);
+ if (r < 0)
+ return r;
+ }
+
+ STRV_FOREACH(file, arg_files) {
+ const char *output_name;
+
+ if (streq(*file, "-")) {
+ log_debug("Using standard input as source.");
+
+ fd = STDIN_FILENO;
+ output_name = "stdin";
+ } else {
+ log_debug("Reading file %s...", *file);
+
+ fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to open %s: %m", *file);
+ output_name = *file;
+ }
+
+ r = journal_remote_add_source(s, fd, (char*) output_name, false);
+ if (r < 0)
+ return r;
+ }
+
+ if (s->active == 0) {
+ log_error("Zero sources specified");
+ return -EINVAL;
+ }
+
+ if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) {
+ /* In this case we know what the writer will be
+ called, so we can create it and verify that we can
+ create output as expected. */
+ r = journal_remote_get_writer(s, NULL, &s->_single_writer);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+static int negative_fd(const char *spec) {
+ /* Return a non-positive number as its inverse, -EINVAL otherwise. */
+
+ int fd, r;
+
+ r = safe_atoi(spec, &fd);
+ if (r < 0)
+ return r;
+
+ if (fd > 0)
+ return -EINVAL;
+ else
+ return -fd;
+}
+
+static int parse_config(void) {
+ const ConfigTableItem items[] = {
+ { "Remote", "Seal", config_parse_bool, 0, &arg_seal },
+ { "Remote", "SplitMode", config_parse_write_split_mode, 0, &arg_split_mode },
+ { "Remote", "ServerKeyFile", config_parse_path, 0, &arg_key },
+ { "Remote", "ServerCertificateFile", config_parse_path, 0, &arg_cert },
+ { "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust },
+ {}};
+
+ return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-remote.conf",
+ CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"),
+ "Remote\0", config_item_table_lookup, items,
+ CONFIG_PARSE_WARN, NULL);
+}
+
+static void help(void) {
+ printf("%s [OPTIONS...] {FILE|-}...\n\n"
+ "Write external journal events to journal file(s).\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --url=URL Read events from systemd-journal-gatewayd at URL\n"
+ " --getter=COMMAND Read events from the output of COMMAND\n"
+ " --listen-raw=ADDR Listen for connections at ADDR\n"
+ " --listen-http=ADDR Listen for HTTP connections at ADDR\n"
+ " --listen-https=ADDR Listen for HTTPS connections at ADDR\n"
+ " -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n"
+ " --compress[=BOOL] XZ-compress the output journal (default: yes)\n"
+ " --seal[=BOOL] Use event sealing (default: no)\n"
+ " --key=FILENAME SSL key in PEM format (default:\n"
+ " \"" PRIV_KEY_FILE "\")\n"
+ " --cert=FILENAME SSL certificate in PEM format (default:\n"
+ " \"" CERT_FILE "\")\n"
+ " --trust=FILENAME|all SSL CA certificate or disable checking (default:\n"
+ " \"" TRUST_FILE "\")\n"
+ " --gnutls-log=CATEGORY...\n"
+ " Specify a list of gnutls logging categories\n"
+ " --split-mode=none|host How many output files to create\n"
+ "\n"
+ "Note: file descriptors from sd_listen_fds() will be consumed, too.\n"
+ , program_invocation_short_name);
+}
+
+static int parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_URL,
+ ARG_LISTEN_RAW,
+ ARG_LISTEN_HTTP,
+ ARG_LISTEN_HTTPS,
+ ARG_GETTER,
+ ARG_SPLIT_MODE,
+ ARG_COMPRESS,
+ ARG_SEAL,
+ ARG_KEY,
+ ARG_CERT,
+ ARG_TRUST,
+ ARG_GNUTLS_LOG,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "url", required_argument, NULL, ARG_URL },
+ { "getter", required_argument, NULL, ARG_GETTER },
+ { "listen-raw", required_argument, NULL, ARG_LISTEN_RAW },
+ { "listen-http", required_argument, NULL, ARG_LISTEN_HTTP },
+ { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
+ { "output", required_argument, NULL, 'o' },
+ { "split-mode", required_argument, NULL, ARG_SPLIT_MODE },
+ { "compress", optional_argument, NULL, ARG_COMPRESS },
+ { "seal", optional_argument, NULL, ARG_SEAL },
+ { "key", required_argument, NULL, ARG_KEY },
+ { "cert", required_argument, NULL, ARG_CERT },
+ { "trust", required_argument, NULL, ARG_TRUST },
+ { "gnutls-log", required_argument, NULL, ARG_GNUTLS_LOG },
+ {}
+ };
+
+ int c, r;
+ bool type_a, type_b;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
+ switch(c) {
+ case 'h':
+ help();
+ return 0 /* done */;
+
+ case ARG_VERSION:
+ return version();
+
+ case ARG_URL:
+ if (arg_url) {
+ log_error("cannot currently set more than one --url");
+ return -EINVAL;
+ }
+
+ arg_url = optarg;
+ break;
+
+ case ARG_GETTER:
+ if (arg_getter) {
+ log_error("cannot currently use --getter more than once");
+ return -EINVAL;
+ }
+
+ arg_getter = optarg;
+ break;
+
+ case ARG_LISTEN_RAW:
+ if (arg_listen_raw) {
+ log_error("cannot currently use --listen-raw more than once");
+ return -EINVAL;
+ }
+
+ arg_listen_raw = optarg;
+ break;
+
+ case ARG_LISTEN_HTTP:
+ if (arg_listen_http || http_socket >= 0) {
+ log_error("cannot currently use --listen-http more than once");
+ return -EINVAL;
+ }
+
+ r = negative_fd(optarg);
+ if (r >= 0)
+ http_socket = r;
+ else
+ arg_listen_http = optarg;
+ break;
+
+ case ARG_LISTEN_HTTPS:
+ if (arg_listen_https || https_socket >= 0) {
+ log_error("cannot currently use --listen-https more than once");
+ return -EINVAL;
+ }
+
+ r = negative_fd(optarg);
+ if (r >= 0)
+ https_socket = r;
+ else
+ arg_listen_https = optarg;
+
+ break;
+
+ case ARG_KEY:
+ if (arg_key) {
+ log_error("Key file specified twice");
+ return -EINVAL;
+ }
+
+ arg_key = strdup(optarg);
+ if (!arg_key)
+ return log_oom();
+
+ break;
+
+ case ARG_CERT:
+ if (arg_cert) {
+ log_error("Certificate file specified twice");
+ return -EINVAL;
+ }
+
+ arg_cert = strdup(optarg);
+ if (!arg_cert)
+ return log_oom();
+
+ break;
+
+ case ARG_TRUST:
+ if (arg_trust || arg_trust_all) {
+ log_error("Confusing trusted CA configuration");
+ return -EINVAL;
+ }
+
+ if (streq(optarg, "all"))
+ arg_trust_all = true;
+ else {
+#if HAVE_GNUTLS
+ arg_trust = strdup(optarg);
+ if (!arg_trust)
+ return log_oom();
+#else
+ log_error("Option --trust is not available.");
+ return -EINVAL;
+#endif
+ }
+
+ break;
+
+ case 'o':
+ if (arg_output) {
+ log_error("cannot use --output/-o more than once");
+ return -EINVAL;
+ }
+
+ arg_output = optarg;
+ break;
+
+ case ARG_SPLIT_MODE:
+ arg_split_mode = journal_write_split_mode_from_string(optarg);
+ if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) {
+ log_error("Invalid split mode: %s", optarg);
+ return -EINVAL;
+ }
+ break;
+
+ case ARG_COMPRESS:
+ if (optarg) {
+ r = parse_boolean(optarg);
+ if (r < 0) {
+ log_error("Failed to parse --compress= parameter.");
+ return -EINVAL;
+ }
+
+ arg_compress = !!r;
+ } else
+ arg_compress = true;
+
+ break;
+
+ case ARG_SEAL:
+ if (optarg) {
+ r = parse_boolean(optarg);
+ if (r < 0) {
+ log_error("Failed to parse --seal= parameter.");
+ return -EINVAL;
+ }
+
+ arg_seal = !!r;
+ } else
+ arg_seal = true;
+
+ break;
+
+ case ARG_GNUTLS_LOG: {
+#if HAVE_GNUTLS
+ const char* p = optarg;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&p, &word, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m");
+
+ if (r == 0)
+ break;
+
+ if (strv_push(&arg_gnutls_log, word) < 0)
+ return log_oom();
+
+ word = NULL;
+ }
+ break;
+#else
+ log_error("Option --gnutls-log is not available.");
+ return -EINVAL;
+#endif
+ }
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unknown option code.");
+ }
+
+ if (optind < argc)
+ arg_files = argv + optind;
+
+ type_a = arg_getter || !strv_isempty(arg_files);
+ type_b = arg_url
+ || arg_listen_raw
+ || arg_listen_http || arg_listen_https
+ || sd_listen_fds(false) > 0;
+ if (type_a && type_b) {
+ log_error("Cannot use file input or --getter with "
+ "--arg-listen-... or socket activation.");
+ return -EINVAL;
+ }
+ if (type_a) {
+ if (!arg_output) {
+ log_error("Option --output must be specified with file input or --getter.");
+ return -EINVAL;
+ }
+
+ if (!IN_SET(arg_split_mode, JOURNAL_WRITE_SPLIT_NONE, _JOURNAL_WRITE_SPLIT_INVALID)) {
+ log_error("For active sources, only --split-mode=none is allowed.");
+ return -EINVAL;
+ }
+
+ arg_split_mode = JOURNAL_WRITE_SPLIT_NONE;
+ }
+
+ if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID)
+ arg_split_mode = JOURNAL_WRITE_SPLIT_HOST;
+
+ if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE && arg_output) {
+ if (is_dir(arg_output, true) > 0) {
+ log_error("For SplitMode=none, output must be a file.");
+ return -EINVAL;
+ }
+ if (!endswith(arg_output, ".journal")) {
+ log_error("For SplitMode=none, output file name must end with .journal.");
+ return -EINVAL;
+ }
+ }
+
+ if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST
+ && arg_output && is_dir(arg_output, true) <= 0) {
+ log_error("For SplitMode=host, output must be a directory.");
+ return -EINVAL;
+ }
+
+ log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",
+ journal_write_split_mode_to_string(arg_split_mode),
+ strna(arg_key),
+ strna(arg_cert),
+ strna(arg_trust));
+
+ return 1 /* work to do */;
+}
+
+static int load_certificates(char **key, char **cert, char **trust) {
+ int r;
+
+ r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read key from file '%s': %m",
+ arg_key ?: PRIV_KEY_FILE);
+
+ r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read certificate from file '%s': %m",
+ arg_cert ?: CERT_FILE);
+
+ if (arg_trust_all)
+ log_info("Certificate checking disabled.");
+ else {
+ r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read CA certificate file '%s': %m",
+ arg_trust ?: TRUST_FILE);
+ }
+
+ if ((arg_listen_raw || arg_listen_http) && *trust) {
+ log_error("Option --trust makes all non-HTTPS connections untrusted.");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ RemoteServer s = {};
+ int r;
+ _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
+
+ log_show_color(true);
+ log_parse_environment();
+
+ r = parse_config();
+ if (r < 0)
+ return EXIT_FAILURE;
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+
+ if (arg_listen_http || arg_listen_https) {
+ r = setup_gnutls_logger(arg_gnutls_log);
+ if (r < 0)
+ return EXIT_FAILURE;
+ }
+
+ if (arg_listen_https || https_socket >= 0)
+ if (load_certificates(&key, &cert, &trust) < 0)
+ return EXIT_FAILURE;
+
+ if (create_remoteserver(&s, key, cert, trust) < 0)
+ return EXIT_FAILURE;
+
+ r = sd_event_set_watchdog(s.events, true);
+ if (r < 0)
+ log_error_errno(r, "Failed to enable watchdog: %m");
+ else
+ log_debug("Watchdog is %sd.", enable_disable(r > 0));
+
+ log_debug("%s running as pid "PID_FMT,
+ program_invocation_short_name, getpid_cached());
+ sd_notify(false,
+ "READY=1\n"
+ "STATUS=Processing requests...");
+
+ while (s.active) {
+ r = sd_event_get_state(s.events);
+ if (r < 0)
+ break;
+ if (r == SD_EVENT_FINISHED)
+ break;
+
+ r = sd_event_run(s.events, -1);
+ if (r < 0) {
+ log_error_errno(r, "Failed to run event loop: %m");
+ break;
+ }
+ }
+
+ sd_notifyf(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
+ log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
+
+ journal_remote_server_destroy(&s);
+
+ free(arg_key);
+ free(arg_cert);
+ free(arg_trust);
+
+ return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c
index 2c4e28ad71..535d06ac76 100644
--- a/src/journal-remote/journal-remote-parse.c
+++ b/src/journal-remote/journal-remote-parse.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "fd-util.h"
@@ -45,7 +27,6 @@ void source_free(RemoteSource *source) {
* ownership of fd, name, and writer, otherwise does not touch them.
*/
RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) {
-
RemoteSource *source;
log_debug("Creating source for %sfd:%d (%s)",
@@ -88,7 +69,10 @@ int process_source(RemoteSource *source, bool compress, bool seal) {
assert(source->importer.iovw.iovec);
r = writer_write(source->writer, &source->importer.iovw, &source->importer.ts, compress, seal);
- if (r < 0)
+ if (r == -EBADMSG) {
+ log_error_errno(r, "Entry is invalid, ignoring.");
+ r = 0;
+ } else if (r < 0)
log_error_errno(r, "Failed to write entry of %zu bytes: %m",
iovw_size(&source->importer.iovw));
else
diff --git a/src/journal-remote/journal-remote-parse.h b/src/journal-remote/journal-remote-parse.h
index 7aa2f0663e..d6c77360a6 100644
--- a/src/journal-remote/journal-remote-parse.h
+++ b/src/journal-remote/journal-remote-parse.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-event.h"
#include "journal-importer.h"
diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c
index c5c6abbd5c..9211e7df82 100644
--- a/src/journal-remote/journal-remote-write.c
+++ b/src/journal-remote/journal-remote-write.c
@@ -1,28 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "journal-remote.h"
static int do_rotate(JournalFile **f, bool compress, bool seal) {
- int r = journal_file_rotate(f, compress, seal, NULL);
+ int r = journal_file_rotate(f, compress, (uint64_t) -1, seal, NULL);
if (r < 0) {
if (*f)
log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
@@ -105,13 +87,15 @@ int writer_write(Writer *w,
return r;
}
- r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count,
+ r = journal_file_append_entry(w->journal, ts, NULL,
+ iovw->iovec, iovw->count,
&w->seqnum, NULL, NULL);
if (r >= 0) {
if (w->server)
w->server->event_count += 1;
- return 1;
- }
+ return 0;
+ } else if (r == -EBADMSG)
+ return r;
log_debug_errno(r, "%s: Write failed, rotating: %m", w->journal->path);
r = do_rotate(&w->journal, compress, seal);
@@ -121,12 +105,13 @@ int writer_write(Writer *w,
log_debug("%s: Successfully rotated journal", w->journal->path);
log_debug("Retrying write.");
- r = journal_file_append_entry(w->journal, ts, iovw->iovec, iovw->count,
+ r = journal_file_append_entry(w->journal, ts, NULL,
+ iovw->iovec, iovw->count,
&w->seqnum, NULL, NULL);
if (r < 0)
return r;
if (w->server)
w->server->event_count += 1;
- return 1;
+ return 0;
}
diff --git a/src/journal-remote/journal-remote-write.h b/src/journal-remote/journal-remote-write.h
index 7fffc294ce..7ed32aa5aa 100644
--- a/src/journal-remote/journal-remote-write.h
+++ b/src/journal-remote/journal-remote-write.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "journal-file.h"
#include "journal-importer.h"
@@ -45,7 +26,6 @@ Writer* writer_ref(Writer *w);
Writer* writer_unref(Writer *w);
DEFINE_TRIVIAL_CLEANUP_FUNC(Writer*, writer_unref);
-#define _cleanup_writer_unref_ _cleanup_(writer_unrefp)
int writer_write(Writer *s,
struct iovec_wrapper *iovw,
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 428725223d..beb75a1cb4 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -1,42 +1,20 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
-#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h>
-#include <unistd.h>
#include <stdint.h>
#include "sd-daemon.h"
#include "alloc-util.h"
-#include "conf-parser.h"
#include "def.h"
#include "escape.h"
#include "fd-util.h"
-#include "fileio.h"
#include "journal-file.h"
#include "journal-remote-write.h"
#include "journal-remote.h"
@@ -44,120 +22,23 @@
#include "macro.h"
#include "parse-util.h"
#include "process-util.h"
-#include "signal-util.h"
#include "socket-util.h"
-#include "stat-util.h"
#include "stdio-util.h"
-#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#define REMOTE_JOURNAL_PATH "/var/log/journal/remote"
-#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem"
-#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem"
-#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem"
-
-static char* arg_url = NULL;
-static char* arg_getter = NULL;
-static char* arg_listen_raw = NULL;
-static char* arg_listen_http = NULL;
-static char* arg_listen_https = NULL;
-static char** arg_files = NULL;
-static int arg_compress = true;
-static int arg_seal = false;
-static int http_socket = -1, https_socket = -1;
-static char** arg_gnutls_log = NULL;
-
-static JournalWriteSplitMode arg_split_mode = _JOURNAL_WRITE_SPLIT_INVALID;
-static char* arg_output = NULL;
-
-static char *arg_key = NULL;
-static char *arg_cert = NULL;
-static char *arg_trust = NULL;
-static bool arg_trust_all = false;
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static int spawn_child(const char* child, char** argv) {
- pid_t child_pid;
- int fd[2], r;
-
- if (pipe(fd) < 0)
- return log_error_errno(errno, "Failed to create pager pipe: %m");
-
- r = safe_fork("(remote)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid);
- if (r < 0) {
- safe_close_pair(fd);
- return r;
- }
-
- /* In the child */
- if (r == 0) {
- safe_close(fd[0]);
-
- r = rearrange_stdio(STDIN_FILENO, fd[1], STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to dup pipe to stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
- execvp(child, argv);
- log_error_errno(errno, "Failed to exec child %s: %m", child);
- _exit(EXIT_FAILURE);
- }
-
- safe_close(fd[1]);
-
- r = fd_nonblock(fd[0], true);
- if (r < 0)
- log_warning_errno(errno, "Failed to set child pipe to non-blocking: %m");
-
- return fd[0];
-}
-
-static int spawn_curl(const char* url) {
- char **argv = STRV_MAKE("curl",
- "-HAccept: application/vnd.fdo.journal",
- "--silent",
- "--show-error",
- url);
- int r;
-
- r = spawn_child("curl", argv);
- if (r < 0)
- log_error_errno(r, "Failed to spawn curl: %m");
- return r;
-}
-
-static int spawn_getter(const char *getter) {
- int r;
- _cleanup_strv_free_ char **words = NULL;
-
- assert(getter);
- r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_QUOTES);
- if (r < 0)
- return log_error_errno(r, "Failed to split getter option: %m");
-
- r = spawn_child(words[0], words);
- if (r < 0)
- log_error_errno(r, "Failed to spawn getter %s: %m", getter);
-
- return r;
-}
-
#define filename_escape(s) xescape((s), "/ ")
-static int open_output(Writer *w, const char* host) {
- _cleanup_free_ char *_output = NULL;
- const char *output;
+static int open_output(RemoteServer *s, Writer *w, const char* host) {
+ _cleanup_free_ char *_filename = NULL;
+ const char *filename;
int r;
- switch (arg_split_mode) {
+ switch (s->split_mode) {
case JOURNAL_WRITE_SPLIT_NONE:
- output = arg_output ?: REMOTE_JOURNAL_PATH "/remote.journal";
+ filename = s->output;
break;
case JOURNAL_WRITE_SPLIT_HOST: {
@@ -169,13 +50,11 @@ static int open_output(Writer *w, const char* host) {
if (!name)
return log_oom();
- r = asprintf(&_output, "%s/remote-%s.journal",
- arg_output ?: REMOTE_JOURNAL_PATH,
- name);
+ r = asprintf(&_filename, "%s/remote-%s.journal", s->output, name);
if (r < 0)
return log_oom();
- output = _output;
+ filename = _filename;
break;
}
@@ -183,18 +62,17 @@ static int open_output(Writer *w, const char* host) {
assert_not_reached("what?");
}
- r = journal_file_open_reliably(output,
+ r = journal_file_open_reliably(filename,
O_RDWR|O_CREAT, 0640,
- arg_compress, arg_seal,
+ s->compress, (uint64_t) -1, s->seal,
&w->metrics,
w->mmap, NULL,
NULL, &w->journal);
if (r < 0)
- log_error_errno(r, "Failed to open output journal %s: %m",
- output);
- else
- log_debug("Opened output file %s", w->journal->path);
- return r;
+ return log_error_errno(r, "Failed to open output journal %s: %m", filename);
+
+ log_debug("Opened output file %s", w->journal->path);
+ return 0;
}
/**********************************************************************
@@ -202,27 +80,27 @@ static int open_output(Writer *w, const char* host) {
**********************************************************************/
static int init_writer_hashmap(RemoteServer *s) {
- static const struct hash_ops *hash_ops[] = {
+ static const struct hash_ops* const hash_ops[] = {
[JOURNAL_WRITE_SPLIT_NONE] = NULL,
[JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops,
};
- assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(hash_ops));
+ assert(s);
+ assert(s->split_mode >= 0 && s->split_mode < (int) ELEMENTSOF(hash_ops));
- s->writers = hashmap_new(hash_ops[arg_split_mode]);
+ s->writers = hashmap_new(hash_ops[s->split_mode]);
if (!s->writers)
return log_oom();
return 0;
}
-static int get_writer(RemoteServer *s, const char *host,
- Writer **writer) {
+int journal_remote_get_writer(RemoteServer *s, const char *host, Writer **writer) {
+ _cleanup_(writer_unrefp) Writer *w = NULL;
const void *key;
- _cleanup_writer_unref_ Writer *w = NULL;
int r;
- switch(arg_split_mode) {
+ switch(s->split_mode) {
case JOURNAL_WRITE_SPLIT_NONE:
key = "one and only";
break;
@@ -244,13 +122,13 @@ static int get_writer(RemoteServer *s, const char *host,
if (!w)
return log_oom();
- if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST) {
+ if (s->split_mode == JOURNAL_WRITE_SPLIT_HOST) {
w->hashmap_key = strdup(key);
if (!w->hashmap_key)
return log_oom();
}
- r = open_output(w, host);
+ r = open_output(s, w, host);
if (r < 0)
return r;
@@ -259,8 +137,8 @@ static int get_writer(RemoteServer *s, const char *host,
return r;
}
- *writer = w;
- w = NULL;
+ *writer = TAKE_PTR(w);
+
return 0;
}
@@ -269,7 +147,7 @@ static int get_writer(RemoteServer *s, const char *host,
**********************************************************************/
/* This should go away as soon as µhttpd allows state to be passed around. */
-static RemoteServer *server;
+RemoteServer *journal_remote_server_global;
static int dispatch_raw_source_event(sd_event_source *event,
int fd,
@@ -283,13 +161,6 @@ static int dispatch_raw_connection_event(sd_event_source *event,
int fd,
uint32_t revents,
void *userdata);
-static int null_timer_event_handler(sd_event_source *s,
- uint64_t usec,
- void *userdata);
-static int dispatch_http_event(sd_event_source *event,
- int fd,
- uint32_t revents,
- void *userdata);
static int get_source_for_fd(RemoteServer *s,
int fd, char *name, RemoteSource **source) {
@@ -304,7 +175,7 @@ static int get_source_for_fd(RemoteServer *s,
if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1))
return log_oom();
- r = get_writer(s, name, &writer);
+ r = journal_remote_get_writer(s, name, &writer);
if (r < 0)
return log_warning_errno(r, "Failed to get writer for source %s: %m",
name);
@@ -340,8 +211,7 @@ static int remove_source(RemoteServer *s, int fd) {
return 0;
}
-static int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
-
+int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name) {
RemoteSource *source = NULL;
int r;
@@ -401,7 +271,7 @@ static int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
return r;
}
-static int add_raw_socket(RemoteServer *s, int fd) {
+int journal_remote_add_raw_socket(RemoteServer *s, int fd) {
int r;
_cleanup_close_ int fd_ = fd;
char name[STRLEN("raw-socket-") + DECIMAL_STR_MAX(int) + 1];
@@ -425,617 +295,63 @@ static int add_raw_socket(RemoteServer *s, int fd) {
return 0;
}
-static int setup_raw_socket(RemoteServer *s, const char *address) {
- int fd;
-
- fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM, SOCK_CLOEXEC);
- if (fd < 0)
- return fd;
-
- return add_raw_socket(s, fd);
-}
-
/**********************************************************************
**********************************************************************
**********************************************************************/
-static int request_meta(void **connection_cls, int fd, char *hostname) {
- RemoteSource *source;
- Writer *writer;
- int r;
-
- assert(connection_cls);
- if (*connection_cls)
- return 0;
-
- r = get_writer(server, hostname, &writer);
- if (r < 0)
- return log_warning_errno(r, "Failed to get writer for source %s: %m",
- hostname);
-
- source = source_new(fd, true, hostname, writer);
- if (!source) {
- writer_unref(writer);
- return log_oom();
- }
-
- log_debug("Added RemoteSource as connection metadata %p", source);
-
- *connection_cls = source;
- return 0;
-}
-
-static void request_meta_free(void *cls,
- struct MHD_Connection *connection,
- void **connection_cls,
- enum MHD_RequestTerminationCode toe) {
- RemoteSource *s;
-
- assert(connection_cls);
- s = *connection_cls;
-
- if (s) {
- log_debug("Cleaning up connection metadata %p", s);
- source_free(s);
- *connection_cls = NULL;
- }
-}
-
-static int process_http_upload(
- struct MHD_Connection *connection,
- const char *upload_data,
- size_t *upload_data_size,
- RemoteSource *source) {
-
- bool finished = false;
- size_t remaining;
- int r;
-
- assert(source);
-
- log_trace("%s: connection %p, %zu bytes",
- __func__, connection, *upload_data_size);
-
- if (*upload_data_size) {
- log_trace("Received %zu bytes", *upload_data_size);
-
- r = journal_importer_push_data(&source->importer,
- upload_data, *upload_data_size);
- if (r < 0)
- return mhd_respond_oom(connection);
-
- *upload_data_size = 0;
- } else
- finished = true;
-
- for (;;) {
- r = process_source(source, arg_compress, arg_seal);
- if (r == -EAGAIN)
- break;
- else if (r < 0) {
- log_warning("Failed to process data for connection %p", connection);
- if (r == -E2BIG)
- return mhd_respondf(connection,
- r, MHD_HTTP_PAYLOAD_TOO_LARGE,
- "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes.");
- else
- return mhd_respondf(connection,
- r, MHD_HTTP_UNPROCESSABLE_ENTITY,
- "Processing failed: %m.");
- }
- }
-
- if (!finished)
- return MHD_YES;
+int journal_remote_server_init(
+ RemoteServer *s,
+ const char *output,
+ JournalWriteSplitMode split_mode,
+ bool compress,
+ bool seal) {
- /* The upload is finished */
-
- remaining = journal_importer_bytes_remaining(&source->importer);
- if (remaining > 0) {
- log_warning("Premature EOF byte. %zu bytes lost.", remaining);
- return mhd_respondf(connection,
- 0, MHD_HTTP_EXPECTATION_FAILED,
- "Premature EOF. %zu bytes of trailing data not processed.",
- remaining);
- }
-
- return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.");
-};
-
-static int request_handler(
- void *cls,
- struct MHD_Connection *connection,
- const char *url,
- const char *method,
- const char *version,
- const char *upload_data,
- size_t *upload_data_size,
- void **connection_cls) {
-
- const char *header;
- int r, code, fd;
- _cleanup_free_ char *hostname = NULL;
-
- assert(connection);
- assert(connection_cls);
- assert(url);
- assert(method);
-
- log_trace("Handling a connection %s %s %s", method, url, version);
-
- if (*connection_cls)
- return process_http_upload(connection,
- upload_data, upload_data_size,
- *connection_cls);
-
- if (!streq(method, "POST"))
- return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method.");
-
- if (!streq(url, "/upload"))
- return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.");
-
- header = MHD_lookup_connection_value(connection,
- MHD_HEADER_KIND, "Content-Type");
- if (!header || !streq(header, "application/vnd.fdo.journal"))
- return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
- "Content-Type: application/vnd.fdo.journal is required.");
-
- {
- const union MHD_ConnectionInfo *ci;
-
- ci = MHD_get_connection_info(connection,
- MHD_CONNECTION_INFO_CONNECTION_FD);
- if (!ci) {
- log_error("MHD_get_connection_info failed: cannot get remote fd");
- return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
- "Cannot check remote address.");
- }
-
- fd = ci->connect_fd;
- assert(fd >= 0);
- }
-
- if (server->check_trust) {
- r = check_permissions(connection, &code, &hostname);
- if (r < 0)
- return code;
- } else {
- r = getpeername_pretty(fd, false, &hostname);
- if (r < 0)
- return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
- "Cannot check remote hostname.");
- }
-
- assert(hostname);
-
- r = request_meta(connection_cls, fd, hostname);
- if (r == -ENOMEM)
- return respond_oom(connection);
- else if (r < 0)
- return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "%m");
-
- hostname = NULL;
- return MHD_YES;
-}
-
-static int setup_microhttpd_server(RemoteServer *s,
- int fd,
- const char *key,
- const char *cert,
- const char *trust) {
- struct MHD_OptionItem opts[] = {
- { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
- { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
- { MHD_OPTION_LISTEN_SOCKET, fd},
- { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024},
- { MHD_OPTION_END},
- { MHD_OPTION_END},
- { MHD_OPTION_END},
- { MHD_OPTION_END},
- { MHD_OPTION_END}};
- int opts_pos = 4;
- int flags =
- MHD_USE_DEBUG |
- MHD_USE_DUAL_STACK |
- MHD_USE_EPOLL |
- MHD_USE_ITC;
-
- const union MHD_DaemonInfo *info;
- int r, epoll_fd;
- MHDDaemonWrapper *d;
-
- assert(fd >= 0);
-
- r = fd_nonblock(fd, true);
- if (r < 0)
- return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd);
-
-/* MHD_OPTION_STRICT_FOR_CLIENT is introduced in microhttpd 0.9.54,
- * and MHD_USE_PEDANTIC_CHECKS will be deprecated in future.
- * If MHD_USE_PEDANTIC_CHECKS is '#define'd, then it is deprecated
- * and we should use MHD_OPTION_STRICT_FOR_CLIENT. On the other hand,
- * if MHD_USE_PEDANTIC_CHECKS is not '#define'd, then it is not
- * deprecated yet and there exists an enum element with the same name.
- * So we can safely use it. */
-#ifdef MHD_USE_PEDANTIC_CHECKS
- opts[opts_pos++] = (struct MHD_OptionItem)
- {MHD_OPTION_STRICT_FOR_CLIENT, 1};
-#else
- flags |= MHD_USE_PEDANTIC_CHECKS;
-#endif
-
- if (key) {
- assert(cert);
-
- opts[opts_pos++] = (struct MHD_OptionItem)
- {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key};
- opts[opts_pos++] = (struct MHD_OptionItem)
- {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert};
-
- flags |= MHD_USE_TLS;
-
- if (trust)
- opts[opts_pos++] = (struct MHD_OptionItem)
- {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust};
- }
-
- d = new(MHDDaemonWrapper, 1);
- if (!d)
- return log_oom();
-
- d->fd = (uint64_t) fd;
-
- d->daemon = MHD_start_daemon(flags, 0,
- NULL, NULL,
- request_handler, NULL,
- MHD_OPTION_ARRAY, opts,
- MHD_OPTION_END);
- if (!d->daemon) {
- log_error("Failed to start µhttp daemon");
- r = -EINVAL;
- goto error;
- }
-
- log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
- key ? "HTTPS" : "HTTP", fd, d);
-
-
- info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
- if (!info) {
- log_error("µhttp returned NULL daemon info");
- r = -EOPNOTSUPP;
- goto error;
- }
-
- epoll_fd = info->listen_fd;
- if (epoll_fd < 0) {
- log_error("µhttp epoll fd is invalid");
- r = -EUCLEAN;
- goto error;
- }
-
- r = sd_event_add_io(s->events, &d->io_event,
- epoll_fd, EPOLLIN,
- dispatch_http_event, d);
- if (r < 0) {
- log_error_errno(r, "Failed to add event callback: %m");
- goto error;
- }
-
- r = sd_event_source_set_description(d->io_event, "io_event");
- if (r < 0) {
- log_error_errno(r, "Failed to set source name: %m");
- goto error;
- }
-
- r = sd_event_add_time(s->events, &d->timer_event,
- CLOCK_MONOTONIC, UINT64_MAX, 0,
- null_timer_event_handler, d);
- if (r < 0) {
- log_error_errno(r, "Failed to add timer_event: %m");
- goto error;
- }
-
- r = sd_event_source_set_description(d->timer_event, "timer_event");
- if (r < 0) {
- log_error_errno(r, "Failed to set source name: %m");
- goto error;
- }
-
- r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops);
- if (r < 0) {
- log_oom();
- goto error;
- }
-
- r = hashmap_put(s->daemons, &d->fd, d);
- if (r < 0) {
- log_error_errno(r, "Failed to add daemon to hashmap: %m");
- goto error;
- }
-
- s->active++;
- return 0;
-
-error:
- MHD_stop_daemon(d->daemon);
- free(d->daemon);
- free(d);
- return r;
-}
-
-static int setup_microhttpd_socket(RemoteServer *s,
- const char *address,
- const char *key,
- const char *cert,
- const char *trust) {
- int fd;
-
- fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM, SOCK_CLOEXEC);
- if (fd < 0)
- return fd;
-
- return setup_microhttpd_server(s, fd, key, cert, trust);
-}
-
-static int null_timer_event_handler(sd_event_source *timer_event,
- uint64_t usec,
- void *userdata) {
- return dispatch_http_event(timer_event, 0, 0, userdata);
-}
-
-static int dispatch_http_event(sd_event_source *event,
- int fd,
- uint32_t revents,
- void *userdata) {
- MHDDaemonWrapper *d = userdata;
- int r;
- MHD_UNSIGNED_LONG_LONG timeout = ULONG_LONG_MAX;
-
- assert(d);
-
- r = MHD_run(d->daemon);
- if (r == MHD_NO) {
- log_error("MHD_run failed!");
- // XXX: unregister daemon
- return -EINVAL;
- }
- if (MHD_get_timeout(d->daemon, &timeout) == MHD_NO)
- timeout = ULONG_LONG_MAX;
-
- r = sd_event_source_set_time(d->timer_event, timeout);
- if (r < 0) {
- log_warning_errno(r, "Unable to set event loop timeout: %m, this may result in indefinite blocking!");
- return 1;
- }
-
- r = sd_event_source_set_enabled(d->timer_event, SD_EVENT_ON);
- if (r < 0)
- log_warning_errno(r, "Unable to enable timer_event: %m, this may result in indefinite blocking!");
-
- return 1; /* work to do */
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static int setup_signals(RemoteServer *s) {
int r;
assert(s);
- assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0);
-
- r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s);
- if (r < 0)
- return r;
-
- r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, NULL, s);
- if (r < 0)
- return r;
+ assert(journal_remote_server_global == NULL);
+ journal_remote_server_global = s;
- return 0;
-}
-
-static int negative_fd(const char *spec) {
- /* Return a non-positive number as its inverse, -EINVAL otherwise. */
-
- int fd, r;
-
- r = safe_atoi(spec, &fd);
- if (r < 0)
- return r;
+ s->split_mode = split_mode;
+ s->compress = compress;
+ s->seal = seal;
- if (fd > 0)
- return -EINVAL;
+ if (output)
+ s->output = output;
+ else if (split_mode == JOURNAL_WRITE_SPLIT_NONE)
+ s->output = REMOTE_JOURNAL_PATH "/remote.journal";
+ else if (split_mode == JOURNAL_WRITE_SPLIT_HOST)
+ s->output = REMOTE_JOURNAL_PATH;
else
- return -fd;
-}
-
-static int remoteserver_init(RemoteServer *s,
- const char* key,
- const char* cert,
- const char* trust) {
- int r, n, fd;
- char **file;
-
- assert(s);
-
- if ((arg_listen_raw || arg_listen_http) && trust) {
- log_error("Option --trust makes all non-HTTPS connections untrusted.");
- return -EINVAL;
- }
+ assert_not_reached("bad split mode");
r = sd_event_default(&s->events);
if (r < 0)
return log_error_errno(r, "Failed to allocate event loop: %m");
- setup_signals(s);
-
- assert(server == NULL);
- server = s;
-
r = init_writer_hashmap(s);
if (r < 0)
return r;
- n = sd_listen_fds(true);
- if (n < 0)
- return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
- else
- log_debug("Received %d descriptors", n);
-
- if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) {
- log_error("Received fewer sockets than expected");
- return -EBADFD;
- }
-
- for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
- if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
- log_debug("Received a listening socket (fd:%d)", fd);
-
- if (fd == http_socket)
- r = setup_microhttpd_server(s, fd, NULL, NULL, NULL);
- else if (fd == https_socket)
- r = setup_microhttpd_server(s, fd, key, cert, trust);
- else
- r = add_raw_socket(s, fd);
- } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
- char *hostname;
-
- r = getpeername_pretty(fd, false, &hostname);
- if (r < 0)
- return log_error_errno(r, "Failed to retrieve remote name: %m");
-
- log_debug("Received a connection socket (fd:%d) from %s", fd, hostname);
-
- r = add_source(s, fd, hostname, true);
- } else {
- log_error("Unknown socket passed on fd:%d", fd);
-
- return -EINVAL;
- }
-
- if (r < 0)
- return log_error_errno(r, "Failed to register socket (fd:%d): %m",
- fd);
- }
-
- if (arg_getter) {
- log_info("Spawning getter %s...", arg_getter);
- fd = spawn_getter(arg_getter);
- if (fd < 0)
- return fd;
-
- r = add_source(s, fd, (char*) arg_output, false);
- if (r < 0)
- return r;
- }
-
- if (arg_url) {
- const char *url;
- char *hostname, *p;
-
- if (!strstr(arg_url, "/entries")) {
- if (endswith(arg_url, "/"))
- url = strjoina(arg_url, "entries");
- else
- url = strjoina(arg_url, "/entries");
- }
- else
- url = strdupa(arg_url);
-
- log_info("Spawning curl %s...", url);
- fd = spawn_curl(url);
- if (fd < 0)
- return fd;
-
- hostname =
- startswith(arg_url, "https://") ?:
- startswith(arg_url, "http://") ?:
- arg_url;
-
- hostname = strdupa(hostname);
- if ((p = strchr(hostname, '/')))
- *p = '\0';
- if ((p = strchr(hostname, ':')))
- *p = '\0';
-
- r = add_source(s, fd, hostname, false);
- if (r < 0)
- return r;
- }
-
- if (arg_listen_raw) {
- log_debug("Listening on a socket...");
- r = setup_raw_socket(s, arg_listen_raw);
- if (r < 0)
- return r;
- }
-
- if (arg_listen_http) {
- r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL);
- if (r < 0)
- return r;
- }
-
- if (arg_listen_https) {
- r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust);
- if (r < 0)
- return r;
- }
-
- STRV_FOREACH(file, arg_files) {
- const char *output_name;
-
- if (streq(*file, "-")) {
- log_debug("Using standard input as source.");
-
- fd = STDIN_FILENO;
- output_name = "stdin";
- } else {
- log_debug("Reading file %s...", *file);
-
- fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
- if (fd < 0)
- return log_error_errno(errno, "Failed to open %s: %m", *file);
- output_name = *file;
- }
-
- r = add_source(s, fd, (char*) output_name, false);
- if (r < 0)
- return r;
- }
-
- if (s->active == 0) {
- log_error("Zero sources specified");
- return -EINVAL;
- }
-
- if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) {
- /* In this case we know what the writer will be
- called, so we can create it and verify that we can
- create output as expected. */
- r = get_writer(s, NULL, &s->_single_writer);
- if (r < 0)
- return r;
- }
-
return 0;
}
+#if HAVE_MICROHTTPD
static void MHDDaemonWrapper_free(MHDDaemonWrapper *d) {
MHD_stop_daemon(d->daemon);
sd_event_source_unref(d->io_event);
sd_event_source_unref(d->timer_event);
free(d);
}
+#endif
-static void server_destroy(RemoteServer *s) {
+RemoteServer* journal_remote_server_destroy(RemoteServer *s) {
size_t i;
+#if HAVE_MICROHTTPD
hashmap_free_with_destructor(s->daemons, MHDDaemonWrapper_free);
+#endif
assert(s->sources_size == 0 || s->sources);
for (i = 0; i < s->sources_size; i++)
@@ -1050,17 +366,22 @@ static void server_destroy(RemoteServer *s) {
sd_event_source_unref(s->listen_event);
sd_event_unref(s->events);
+ if (s == journal_remote_server_global)
+ journal_remote_server_global = NULL;
+
/* fds that we're listening on remain open... */
+ return NULL;
}
/**********************************************************************
**********************************************************************
**********************************************************************/
-static int handle_raw_source(sd_event_source *event,
- int fd,
- uint32_t revents,
- RemoteServer *s) {
+int journal_remote_handle_raw_source(
+ sd_event_source *event,
+ int fd,
+ uint32_t revents,
+ RemoteServer *s) {
RemoteSource *source;
int r;
@@ -1073,7 +394,7 @@ static int handle_raw_source(sd_event_source *event,
source = s->sources[fd];
assert(source->importer.fd == fd);
- r = process_source(source, arg_compress, arg_seal);
+ r = process_source(source, s->compress, s->seal);
if (journal_importer_eof(&source->importer)) {
size_t remaining;
@@ -1093,7 +414,7 @@ static int handle_raw_source(sd_event_source *event,
return 0;
} else if (r < 0) {
log_debug_errno(r, "Closing connection: %m");
- remove_source(server, fd);
+ remove_source(s, fd);
return 0;
} else
return 1;
@@ -1107,7 +428,7 @@ static int dispatch_raw_source_until_block(sd_event_source *event,
/* Make sure event stays around even if source is destroyed */
sd_event_source_ref(event);
- r = handle_raw_source(event, source->importer.fd, EPOLLIN, server);
+ r = journal_remote_handle_raw_source(event, source->importer.fd, EPOLLIN, journal_remote_server_global);
if (r != 1)
/* No more data for now */
sd_event_source_set_enabled(event, SD_EVENT_OFF);
@@ -1127,7 +448,7 @@ static int dispatch_raw_source_event(sd_event_source *event,
assert(source->event);
assert(source->buffer_event);
- r = handle_raw_source(event, fd, EPOLLIN, server);
+ r = journal_remote_handle_raw_source(event, fd, EPOLLIN, journal_remote_server_global);
if (r == 1)
/* Might have more data. We need to rerun the handler
* until we are sure the buffer is exhausted. */
@@ -1140,7 +461,7 @@ static int dispatch_blocking_source_event(sd_event_source *event,
void *userdata) {
RemoteSource *source = userdata;
- return handle_raw_source(event, source->importer.fd, EPOLLIN, server);
+ return journal_remote_handle_raw_source(event, source->importer.fd, EPOLLIN, journal_remote_server_global);
}
static int accept_connection(const char* type, int fd,
@@ -1206,440 +527,5 @@ static int dispatch_raw_connection_event(sd_event_source *event,
if (fd2 < 0)
return fd2;
- return add_source(s, fd2, hostname, true);
-}
-
-/**********************************************************************
- **********************************************************************
- **********************************************************************/
-
-static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
- [JOURNAL_WRITE_SPLIT_NONE] = "none",
- [JOURNAL_WRITE_SPLIT_HOST] = "host",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode);
-static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
- journal_write_split_mode,
- JournalWriteSplitMode,
- "Failed to parse split mode setting");
-
-static int parse_config(void) {
- const ConfigTableItem items[] = {
- { "Remote", "Seal", config_parse_bool, 0, &arg_seal },
- { "Remote", "SplitMode", config_parse_write_split_mode, 0, &arg_split_mode },
- { "Remote", "ServerKeyFile", config_parse_path, 0, &arg_key },
- { "Remote", "ServerCertificateFile", config_parse_path, 0, &arg_cert },
- { "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust },
- {}};
-
- return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-remote.conf",
- CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"),
- "Remote\0", config_item_table_lookup, items,
- CONFIG_PARSE_WARN, NULL);
-}
-
-static void help(void) {
- printf("%s [OPTIONS...] {FILE|-}...\n\n"
- "Write external journal events to journal file(s).\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --url=URL Read events from systemd-journal-gatewayd at URL\n"
- " --getter=COMMAND Read events from the output of COMMAND\n"
- " --listen-raw=ADDR Listen for connections at ADDR\n"
- " --listen-http=ADDR Listen for HTTP connections at ADDR\n"
- " --listen-https=ADDR Listen for HTTPS connections at ADDR\n"
- " -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n"
- " --compress[=BOOL] XZ-compress the output journal (default: yes)\n"
- " --seal[=BOOL] Use event sealing (default: no)\n"
- " --key=FILENAME SSL key in PEM format (default:\n"
- " \"" PRIV_KEY_FILE "\")\n"
- " --cert=FILENAME SSL certificate in PEM format (default:\n"
- " \"" CERT_FILE "\")\n"
- " --trust=FILENAME|all SSL CA certificate or disable checking (default:\n"
- " \"" TRUST_FILE "\")\n"
- " --gnutls-log=CATEGORY...\n"
- " Specify a list of gnutls logging categories\n"
- " --split-mode=none|host How many output files to create\n"
- "\n"
- "Note: file descriptors from sd_listen_fds() will be consumed, too.\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_URL,
- ARG_LISTEN_RAW,
- ARG_LISTEN_HTTP,
- ARG_LISTEN_HTTPS,
- ARG_GETTER,
- ARG_SPLIT_MODE,
- ARG_COMPRESS,
- ARG_SEAL,
- ARG_KEY,
- ARG_CERT,
- ARG_TRUST,
- ARG_GNUTLS_LOG,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "url", required_argument, NULL, ARG_URL },
- { "getter", required_argument, NULL, ARG_GETTER },
- { "listen-raw", required_argument, NULL, ARG_LISTEN_RAW },
- { "listen-http", required_argument, NULL, ARG_LISTEN_HTTP },
- { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
- { "output", required_argument, NULL, 'o' },
- { "split-mode", required_argument, NULL, ARG_SPLIT_MODE },
- { "compress", optional_argument, NULL, ARG_COMPRESS },
- { "seal", optional_argument, NULL, ARG_SEAL },
- { "key", required_argument, NULL, ARG_KEY },
- { "cert", required_argument, NULL, ARG_CERT },
- { "trust", required_argument, NULL, ARG_TRUST },
- { "gnutls-log", required_argument, NULL, ARG_GNUTLS_LOG },
- {}
- };
-
- int c, r;
- bool type_a, type_b;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
- switch(c) {
- case 'h':
- help();
- return 0 /* done */;
-
- case ARG_VERSION:
- return version();
-
- case ARG_URL:
- if (arg_url) {
- log_error("cannot currently set more than one --url");
- return -EINVAL;
- }
-
- arg_url = optarg;
- break;
-
- case ARG_GETTER:
- if (arg_getter) {
- log_error("cannot currently use --getter more than once");
- return -EINVAL;
- }
-
- arg_getter = optarg;
- break;
-
- case ARG_LISTEN_RAW:
- if (arg_listen_raw) {
- log_error("cannot currently use --listen-raw more than once");
- return -EINVAL;
- }
-
- arg_listen_raw = optarg;
- break;
-
- case ARG_LISTEN_HTTP:
- if (arg_listen_http || http_socket >= 0) {
- log_error("cannot currently use --listen-http more than once");
- return -EINVAL;
- }
-
- r = negative_fd(optarg);
- if (r >= 0)
- http_socket = r;
- else
- arg_listen_http = optarg;
- break;
-
- case ARG_LISTEN_HTTPS:
- if (arg_listen_https || https_socket >= 0) {
- log_error("cannot currently use --listen-https more than once");
- return -EINVAL;
- }
-
- r = negative_fd(optarg);
- if (r >= 0)
- https_socket = r;
- else
- arg_listen_https = optarg;
-
- break;
-
- case ARG_KEY:
- if (arg_key) {
- log_error("Key file specified twice");
- return -EINVAL;
- }
-
- arg_key = strdup(optarg);
- if (!arg_key)
- return log_oom();
-
- break;
-
- case ARG_CERT:
- if (arg_cert) {
- log_error("Certificate file specified twice");
- return -EINVAL;
- }
-
- arg_cert = strdup(optarg);
- if (!arg_cert)
- return log_oom();
-
- break;
-
- case ARG_TRUST:
- if (arg_trust || arg_trust_all) {
- log_error("Confusing trusted CA configuration");
- return -EINVAL;
- }
-
- if (streq(optarg, "all"))
- arg_trust_all = true;
- else {
-#if HAVE_GNUTLS
- arg_trust = strdup(optarg);
- if (!arg_trust)
- return log_oom();
-#else
- log_error("Option --trust is not available.");
- return -EINVAL;
-#endif
- }
-
- break;
-
- case 'o':
- if (arg_output) {
- log_error("cannot use --output/-o more than once");
- return -EINVAL;
- }
-
- arg_output = optarg;
- break;
-
- case ARG_SPLIT_MODE:
- arg_split_mode = journal_write_split_mode_from_string(optarg);
- if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) {
- log_error("Invalid split mode: %s", optarg);
- return -EINVAL;
- }
- break;
-
- case ARG_COMPRESS:
- if (optarg) {
- r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --compress= parameter.");
- return -EINVAL;
- }
-
- arg_compress = !!r;
- } else
- arg_compress = true;
-
- break;
-
- case ARG_SEAL:
- if (optarg) {
- r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --seal= parameter.");
- return -EINVAL;
- }
-
- arg_seal = !!r;
- } else
- arg_seal = true;
-
- break;
-
- case ARG_GNUTLS_LOG: {
-#if HAVE_GNUTLS
- const char* p = optarg;
- for (;;) {
- _cleanup_free_ char *word = NULL;
-
- r = extract_first_word(&p, &word, ",", 0);
- if (r < 0)
- return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m");
-
- if (r == 0)
- break;
-
- if (strv_push(&arg_gnutls_log, word) < 0)
- return log_oom();
-
- word = NULL;
- }
- break;
-#else
- log_error("Option --gnutls-log is not available.");
- return -EINVAL;
-#endif
- }
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unknown option code.");
- }
-
- if (optind < argc)
- arg_files = argv + optind;
-
- type_a = arg_getter || !strv_isempty(arg_files);
- type_b = arg_url
- || arg_listen_raw
- || arg_listen_http || arg_listen_https
- || sd_listen_fds(false) > 0;
- if (type_a && type_b) {
- log_error("Cannot use file input or --getter with "
- "--arg-listen-... or socket activation.");
- return -EINVAL;
- }
- if (type_a) {
- if (!arg_output) {
- log_error("Option --output must be specified with file input or --getter.");
- return -EINVAL;
- }
-
- if (!IN_SET(arg_split_mode, JOURNAL_WRITE_SPLIT_NONE, _JOURNAL_WRITE_SPLIT_INVALID)) {
- log_error("For active sources, only --split-mode=none is allowed.");
- return -EINVAL;
- }
-
- arg_split_mode = JOURNAL_WRITE_SPLIT_NONE;
- }
-
- if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID)
- arg_split_mode = JOURNAL_WRITE_SPLIT_HOST;
-
- if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE && arg_output) {
- if (is_dir(arg_output, true) > 0) {
- log_error("For SplitMode=none, output must be a file.");
- return -EINVAL;
- }
- if (!endswith(arg_output, ".journal")) {
- log_error("For SplitMode=none, output file name must end with .journal.");
- return -EINVAL;
- }
- }
-
- if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST
- && arg_output && is_dir(arg_output, true) <= 0) {
- log_error("For SplitMode=host, output must be a directory.");
- return -EINVAL;
- }
-
- log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",
- journal_write_split_mode_to_string(arg_split_mode),
- strna(arg_key),
- strna(arg_cert),
- strna(arg_trust));
-
- return 1 /* work to do */;
-}
-
-static int load_certificates(char **key, char **cert, char **trust) {
- int r;
-
- r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to read key from file '%s': %m",
- arg_key ?: PRIV_KEY_FILE);
-
- r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to read certificate from file '%s': %m",
- arg_cert ?: CERT_FILE);
-
- if (arg_trust_all)
- log_info("Certificate checking disabled.");
- else {
- r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to read CA certificate file '%s': %m",
- arg_trust ?: TRUST_FILE);
- }
-
- return 0;
-}
-
-int main(int argc, char **argv) {
- RemoteServer s = {};
- int r;
- _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
-
- log_show_color(true);
- log_parse_environment();
-
- r = parse_config();
- if (r < 0)
- return EXIT_FAILURE;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-
-
- if (arg_listen_http || arg_listen_https) {
- r = setup_gnutls_logger(arg_gnutls_log);
- if (r < 0)
- return EXIT_FAILURE;
- }
-
- if (arg_listen_https || https_socket >= 0)
- if (load_certificates(&key, &cert, &trust) < 0)
- return EXIT_FAILURE;
-
- if (remoteserver_init(&s, key, cert, trust) < 0)
- return EXIT_FAILURE;
-
- r = sd_event_set_watchdog(s.events, true);
- if (r < 0)
- log_error_errno(r, "Failed to enable watchdog: %m");
- else
- log_debug("Watchdog is %sd.", enable_disable(r > 0));
-
- log_debug("%s running as pid "PID_FMT,
- program_invocation_short_name, getpid_cached());
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
-
- while (s.active) {
- r = sd_event_get_state(s.events);
- if (r < 0)
- break;
- if (r == SD_EVENT_FINISHED)
- break;
-
- r = sd_event_run(s.events, -1);
- if (r < 0) {
- log_error_errno(r, "Failed to run event loop: %m");
- break;
- }
- }
-
- sd_notifyf(false,
- "STOPPING=1\n"
- "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
- log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
-
- server_destroy(&s);
-
- free(arg_key);
- free(arg_cert);
- free(arg_trust);
-
- return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ return journal_remote_add_source(s, fd2, hostname, true);
}
diff --git a/src/journal-remote/journal-remote.h b/src/journal-remote/journal-remote.h
index 30e5c4e995..e083ea9c74 100644
--- a/src/journal-remote/journal-remote.h
+++ b/src/journal-remote/journal-remote.h
@@ -1,30 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-event.h"
#include "hashmap.h"
#include "journal-remote-parse.h"
#include "journal-remote-write.h"
+
+#if HAVE_MICROHTTPD
#include "microhttpd-util.h"
typedef struct MHDDaemonWrapper MHDDaemonWrapper;
@@ -36,6 +19,7 @@ struct MHDDaemonWrapper {
sd_event_source *io_event;
sd_event_source *timer_event;
};
+#endif
struct RemoteServer {
RemoteSource **sources;
@@ -49,6 +33,33 @@ struct RemoteServer {
Writer *_single_writer;
uint64_t event_count;
- bool check_trust;
+#if HAVE_MICROHTTPD
Hashmap *daemons;
+#endif
+ const char *output; /* either the output file or directory */
+
+ JournalWriteSplitMode split_mode;
+ bool compress;
+ bool seal;
+ bool check_trust;
};
+extern RemoteServer *journal_remote_server_global;
+
+int journal_remote_server_init(
+ RemoteServer *s,
+ const char *output,
+ JournalWriteSplitMode split_mode,
+ bool compress,
+ bool seal);
+
+int journal_remote_get_writer(RemoteServer *s, const char *host, Writer **writer);
+
+int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name);
+int journal_remote_add_raw_socket(RemoteServer *s, int fd);
+int journal_remote_handle_raw_source(
+ sd_event_source *event,
+ int fd,
+ uint32_t revents,
+ RemoteServer *s);
+
+RemoteServer* journal_remote_server_destroy(RemoteServer *s);
diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
index 6c214d27fc..3991dcb7d2 100644
--- a/src/journal-remote/journal-upload-journal.c
+++ b/src/journal-remote/journal-upload-journal.c
@@ -1,32 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <curl/curl.h>
#include <stdbool.h>
+#include "sd-daemon.h"
+
#include "alloc-util.h"
#include "journal-upload.h"
#include "log.h"
+#include "string-util.h"
#include "utf8.h"
#include "util.h"
-#include "sd-daemon.h"
/**
* Write up to size bytes to buf. Return negative on error, and number of
@@ -152,8 +136,12 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
continue;
}
- if (!utf8_is_printable_newline(u->field_data,
- u->field_length, false)) {
+ /* We already printed the boot id from the data in
+ * the header, hence let's suppress it here */
+ if (memory_startswith(u->field_data, u->field_length, "_BOOT_ID="))
+ continue;
+
+ if (!utf8_is_printable_newline(u->field_data, u->field_length, false)) {
u->entry_state = ENTRY_BINARY_FIELD_START;
continue;
}
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index 3094785618..209e5011d9 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <curl/curl.h>
#include <fcntl.h>
@@ -165,7 +147,7 @@ static int load_cursor_state(Uploader *u) {
if (!u->state_file)
return 0;
- r = parse_env_file(u->state_file, NEWLINE,
+ r = parse_env_file(NULL, u->state_file, NEWLINE,
"LAST_CURSOR", &u->last_cursor,
NULL);
@@ -180,8 +162,6 @@ static int load_cursor_state(Uploader *u) {
return 0;
}
-
-
int start_upload(Uploader *u,
size_t (*input_callback)(void *ptr,
size_t size,
diff --git a/src/journal-remote/log-generator.py b/src/journal-remote/log-generator.py
index c2f945bb47..e1725b1a71 100755
--- a/src/journal-remote/log-generator.py
+++ b/src/journal-remote/log-generator.py
@@ -5,7 +5,8 @@ import argparse
PARSER = argparse.ArgumentParser()
PARSER.add_argument('n', type=int)
PARSER.add_argument('--dots', action='store_true')
-PARSER.add_argument('--data-size', type=int, default=4000)
+PARSER.add_argument('-m', '--message-size', type=int, default=200)
+PARSER.add_argument('-d', '--data-size', type=int, default=4000)
PARSER.add_argument('--data-type', choices={'random', 'simple'})
OPTIONS = PARSER.parse_args()
@@ -42,7 +43,9 @@ bytes = 0
counter = 0
for i in range(OPTIONS.n):
- message = repr(src.read(2000))
+ message = src.read(OPTIONS.message_size)
+ message = repr(message)[2:-1]
+
if OPTIONS.data_type == 'random':
data = repr(src.read(OPTIONS.data_size))
else:
diff --git a/src/journal-remote/meson.build b/src/journal-remote/meson.build
index cbe2be19c7..2887daa4bf 100644
--- a/src/journal-remote/meson.build
+++ b/src/journal-remote/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
systemd_journal_upload_sources = files('''
journal-upload.h
@@ -21,15 +6,35 @@ systemd_journal_upload_sources = files('''
journal-upload-journal.c
'''.split())
-systemd_journal_remote_sources = files('''
+libsystemd_journal_remote_sources = files('''
journal-remote-parse.h
journal-remote-parse.c
journal-remote-write.h
journal-remote-write.c
journal-remote.h
journal-remote.c
- microhttpd-util.h
- microhttpd-util.c
+'''.split())
+
+if conf.get('HAVE_MICROHTTPD') == 1
+ libsystemd_journal_remote_sources += files('''
+ microhttpd-util.h
+ microhttpd-util.c
+'''.split())
+endif
+
+libsystemd_journal_remote = static_library(
+ 'systemd-journal-remote',
+ libsystemd_journal_remote_sources,
+ include_directories : includes,
+ dependencies : [threads,
+ libmicrohttpd,
+ libgnutls,
+ libxz,
+ liblz4],
+ install : false)
+
+systemd_journal_remote_sources = files('''
+ journal-remote-main.c
'''.split())
systemd_journal_gatewayd_sources = files('''
diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c
index 2466c4f2b5..34dd9ea555 100644
--- a/src/journal-remote/microhttpd-util.c
+++ b/src/journal-remote/microhttpd-util.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
#include <stdio.h>
@@ -46,7 +27,6 @@ void microhttpd_logger(void *arg, const char *fmt, va_list ap) {
REENABLE_WARNING;
}
-
static int mhd_respond_internal(struct MHD_Connection *connection,
enum MHD_RequestTerminationCode code,
const char *buffer,
@@ -314,10 +294,8 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn
log_debug("Connection from %s", buf);
- if (hostname) {
- *hostname = buf;
- buf = NULL;
- }
+ if (hostname)
+ *hostname = TAKE_PTR(buf);
r = verify_cert_authorized(session);
if (r < 0) {
diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h
index 76a713068e..a50a2a75c7 100644
--- a/src/journal-remote/microhttpd-util.h
+++ b/src/journal-remote/microhttpd-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <microhttpd.h>
#include <stdarg.h>
diff --git a/src/journal/audit-type.c b/src/journal/audit-type.c
index 0af0364e95..b30963da66 100644
--- a/src/journal/audit-type.c
+++ b/src/journal/audit-type.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 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 <linux/audit.h>
diff --git a/src/journal/audit-type.h b/src/journal/audit-type.h
index 603ad41cc7..965b044cbf 100644
--- a/src/journal/audit-type.h
+++ b/src/journal/audit-type.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 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 "macro.h"
const char *audit_type_to_string(int type);
diff --git a/src/journal/cat.c b/src/journal/cat.c
index 1815d58158..8a11c8c3d1 100644
--- a/src/journal/cat.c
+++ b/src/journal/cat.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/journal/catalog.c b/src/journal/catalog.c
index 6775535b17..f9118f0b62 100644
--- a/src/journal/catalog.c
+++ b/src/journal/catalog.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -461,7 +443,7 @@ error:
int catalog_update(const char* database, const char* root, const char* const* dirs) {
_cleanup_strv_free_ char **files = NULL;
char **f;
- struct strbuf *sb = NULL;
+ _cleanup_(strbuf_cleanupp) struct strbuf *sb = NULL;
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
_cleanup_free_ CatalogItem *items = NULL;
ssize_t offset;
@@ -474,38 +456,29 @@ int catalog_update(const char* database, const char* root, const char* const* di
h = hashmap_new(&catalog_hash_ops);
sb = strbuf_new();
-
- if (!h || !sb) {
- r = log_oom();
- goto finish;
- }
+ if (!h || !sb)
+ return log_oom();
r = conf_files_list_strv(&files, ".catalog", root, 0, dirs);
- if (r < 0) {
- log_error_errno(r, "Failed to get catalog files: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get catalog files: %m");
STRV_FOREACH(f, files) {
log_debug("Reading file '%s'", *f);
r = catalog_import_file(h, *f);
- if (r < 0) {
- log_error_errno(r, "Failed to import file '%s': %m", *f);
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to import file '%s': %m", *f);
}
if (hashmap_size(h) <= 0) {
log_info("No items in catalog.");
- goto finish;
+ return 0;
} else
log_debug("Found %u items in catalog.", hashmap_size(h));
items = new(CatalogItem, hashmap_size(h));
- if (!items) {
- r = log_oom();
- goto finish;
- }
+ if (!items)
+ return log_oom();
n = 0;
HASHMAP_FOREACH_KEY(payload, i, h, j) {
@@ -514,10 +487,9 @@ int catalog_update(const char* database, const char* root, const char* const* di
isempty(i->language) ? "C" : i->language);
offset = strbuf_add_string(sb, payload, strlen(payload));
- if (offset < 0) {
- r = log_oom();
- goto finish;
- }
+ if (offset < 0)
+ return log_oom();
+
i->offset = htole64((uint64_t) offset);
items[n++] = *i;
}
@@ -529,17 +501,11 @@ int catalog_update(const char* database, const char* root, const char* const* di
sz = write_catalog(database, sb, items, n);
if (sz < 0)
- r = log_error_errno(sz, "Failed to write %s: %m", database);
- else {
- r = 0;
- log_debug("%s: wrote %u items, with %zu bytes of strings, %"PRIi64" total size.",
- database, n, sb->len, sz);
- }
-
-finish:
- strbuf_cleanup(sb);
+ return log_error_errno(sz, "Failed to write %s: %m", database);
- return r;
+ log_debug("%s: wrote %u items, with %zu bytes of strings, %"PRIi64" total size.",
+ database, n, sb->len, sz);
+ return 0;
}
static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p) {
@@ -592,13 +558,10 @@ static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p
}
static const char *find_id(void *p, sd_id128_t id) {
- CatalogItem key, *f = NULL;
+ CatalogItem *f = NULL, key = { .id = id };
const CatalogHeader *h = p;
const char *loc;
- zero(key);
- key.id = id;
-
loc = setlocale(LC_MESSAGES, NULL);
if (loc && loc[0] && !streq(loc, "C") && !streq(loc, "POSIX")) {
strncpy(key.language, loc, sizeof(key.language));
@@ -697,7 +660,6 @@ static void dump_catalog_entry(FILE *f, sd_id128_t id, const char *s, bool oneli
SD_ID128_FORMAT_VAL(id), s);
}
-
int catalog_list(FILE *f, const char *database, bool oneline) {
_cleanup_close_ int fd = -1;
void *p = NULL;
diff --git a/src/journal/catalog.h b/src/journal/catalog.h
index ce4fa07555..4e6f161af3 100644
--- a/src/journal/catalog.h
+++ b/src/journal/catalog.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "sd-id128.h"
diff --git a/src/journal/compress.c b/src/journal/compress.c
index 92eb3874fd..6baf15c8ff 100644
--- a/src/journal/compress.c
+++ b/src/journal/compress.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <inttypes.h>
#include <stdlib.h>
@@ -130,7 +112,6 @@ int compress_blob_lz4(const void *src, uint64_t src_size,
#endif
}
-
int decompress_blob_xz(const void *src, uint64_t src_size,
void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) {
@@ -244,7 +225,6 @@ int decompress_blob(int compression,
return -EBADMSG;
}
-
int decompress_startswith_xz(const void *src, uint64_t src_size,
void **buffer, size_t *buffer_size,
const void *prefix, size_t prefix_len,
diff --git a/src/journal/compress.h b/src/journal/compress.h
index 917bef0391..56411484ce 100644
--- a/src/journal/compress.h
+++ b/src/journal/compress.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <unistd.h>
#include "journal-def.h"
diff --git a/src/journal/fsprg.c b/src/journal/fsprg.c
index 281b48904a..6d062de5f4 100644
--- a/src/journal/fsprg.c
+++ b/src/journal/fsprg.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+
*
* fsprg v0.1 - (seekable) forward-secure pseudorandom generator
- * Copyright (C) 2012 B. Poettering
+ * Copyright © 2012 B. Poettering
* Contact: fsprg@point-at-infinity.org
*
* This library is free software; you can redistribute it and/or
diff --git a/src/journal/fsprg.h b/src/journal/fsprg.h
index e0ec8884be..bf78c3e9c3 100644
--- a/src/journal/fsprg.h
+++ b/src/journal/fsprg.h
@@ -5,7 +5,7 @@
/*
* fsprg v0.1 - (seekable) forward-secure pseudorandom generator
- * Copyright (C) 2012 B. Poettering
+ * Copyright © 2012 B. Poettering
* Contact: fsprg@point-at-infinity.org
*
* This library is free software; you can redistribute it and/or
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
index cff64749a8..8a9ce8a0d0 100644
--- a/src/journal/journal-authenticate.c
+++ b/src/journal/journal-authenticate.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <sys/mman.h>
diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h
index e2866ea258..2ef0133040 100644
--- a/src/journal/journal-authenticate.h
+++ b/src/journal/journal-authenticate.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "journal-file.h"
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
index 70ce1ab126..43f70c861a 100644
--- a/src/journal/journal-def.h
+++ b/src/journal/journal-def.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-id128.h"
#include "macro.h"
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 9a225060b6..62e7f68a13 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -51,7 +33,8 @@
#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
#define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
-#define COMPRESSION_SIZE_THRESHOLD (512ULL)
+#define DEFAULT_COMPRESS_THRESHOLD (512ULL)
+#define MIN_COMPRESS_THRESHOLD (8ULL)
/* This is the minimum journal file size */
#define JOURNAL_FILE_SIZE_MIN (512ULL*1024ULL) /* 512 KiB */
@@ -224,7 +207,7 @@ int journal_file_set_offline(JournalFile *f, bool wait) {
if (!f->writable)
return -EPERM;
- if (!(f->fd >= 0 && f->header))
+ if (f->fd < 0 || !f->header)
return -EINVAL;
/* An offlining journal is implicitly online and may modify f->header->state,
@@ -274,33 +257,35 @@ int journal_file_set_offline(JournalFile *f, bool wait) {
}
static int journal_file_set_online(JournalFile *f) {
- bool joined = false;
+ bool wait = true;
assert(f);
if (!f->writable)
return -EPERM;
- if (!(f->fd >= 0 && f->header))
+ if (f->fd < 0 || !f->header)
return -EINVAL;
- while (!joined) {
+ while (wait) {
switch (f->offline_state) {
case OFFLINE_JOINED:
/* No offline thread, no need to wait. */
- joined = true;
+ wait = false;
break;
case OFFLINE_SYNCING:
if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_CANCEL))
continue;
/* Canceled syncing prior to offlining, no need to wait. */
+ wait = false;
break;
case OFFLINE_AGAIN_FROM_SYNCING:
if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_SYNCING, OFFLINE_CANCEL))
continue;
/* Canceled restart from syncing, no need to wait. */
+ wait = false;
break;
case OFFLINE_AGAIN_FROM_OFFLINING:
@@ -315,7 +300,7 @@ static int journal_file_set_online(JournalFile *f) {
if (r < 0)
return r;
- joined = true;
+ wait = false;
break;
}
}
@@ -463,16 +448,16 @@ static int journal_file_refresh_header(JournalFile *f) {
assert(f->header);
r = sd_id128_get_machine(&f->header->machine_id);
- if (r < 0)
+ if (IN_SET(r, -ENOENT, -ENOMEDIUM))
+ /* We don't have a machine-id, let's continue without */
+ zero(f->header->machine_id);
+ else if (r < 0)
return r;
r = sd_id128_get_boot(&boot_id);
if (r < 0)
return r;
- if (sd_id128_equal(boot_id, f->header->boot_id))
- f->tail_entry_monotonic_valid = true;
-
f->header->boot_id = boot_id;
r = journal_file_set_online(f);
@@ -689,7 +674,7 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
}
/* Increase by larger blocks at once */
- new_size = ((new_size+FILE_SIZE_INCREASE-1) / FILE_SIZE_INCREASE) * FILE_SIZE_INCREASE;
+ new_size = DIV_ROUND_UP(new_size, FILE_SIZE_INCREASE) * FILE_SIZE_INCREASE;
if (f->metrics.max_size > 0 && new_size > f->metrics.max_size)
new_size = f->metrics.max_size;
@@ -1552,7 +1537,7 @@ static int journal_file_append_data(
o->data.hash = htole64(hash);
#if HAVE_XZ || HAVE_LZ4
- if (JOURNAL_FILE_COMPRESS(f) && size >= COMPRESSION_SIZE_THRESHOLD) {
+ if (JOURNAL_FILE_COMPRESS(f) && size >= f->compress_threshold_bytes) {
size_t rsize = 0;
compression = compress_blob(data, size, o->data.payload, size - 1, &rsize);
@@ -1797,8 +1782,6 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) {
f->header->tail_entry_realtime = o->entry.realtime;
f->header->tail_entry_monotonic = o->entry.monotonic;
- f->tail_entry_monotonic_valid = true;
-
/* Link up the items */
n = journal_file_entry_n_items(o);
for (i = 0; i < n; i++) {
@@ -1813,6 +1796,7 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) {
static int journal_file_append_entry_internal(
JournalFile *f,
const dual_timestamp *ts,
+ const sd_id128_t *boot_id,
uint64_t xor_hash,
const EntryItem items[], unsigned n_items,
uint64_t *seqnum,
@@ -1838,7 +1822,7 @@ static int journal_file_append_entry_internal(
o->entry.realtime = htole64(ts->realtime);
o->entry.monotonic = htole64(ts->monotonic);
o->entry.xor_hash = htole64(xor_hash);
- o->entry.boot_id = f->header->boot_id;
+ o->entry.boot_id = boot_id ? *boot_id : f->header->boot_id;
#if HAVE_GCRYPT
r = journal_file_hmac_put_object(f, OBJECT_ENTRY, o, np);
@@ -1943,8 +1927,7 @@ int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t)
if (r < 0)
return r;
- f->post_change_timer = timer;
- timer = NULL;
+ f->post_change_timer = TAKE_PTR(timer);
f->post_change_timer_period = t;
return r;
@@ -1960,7 +1943,14 @@ static int entry_item_cmp(const void *_a, const void *_b) {
return 0;
}
-int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqnum, Object **ret, uint64_t *offset) {
+int journal_file_append_entry(
+ JournalFile *f,
+ const dual_timestamp *ts,
+ const sd_id128_t *boot_id,
+ const struct iovec iovec[], unsigned n_iovec,
+ uint64_t *seqnum,
+ Object **ret, uint64_t *offset) {
+
unsigned i;
EntryItem *items;
int r;
@@ -1971,7 +1961,16 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
assert(f->header);
assert(iovec || n_iovec == 0);
- if (!ts) {
+ if (ts) {
+ if (!VALID_REALTIME(ts->realtime)) {
+ log_debug("Invalid realtime timestamp %"PRIu64", refusing entry.", ts->realtime);
+ return -EBADMSG;
+ }
+ if (!VALID_MONOTONIC(ts->monotonic)) {
+ log_debug("Invalid monotomic timestamp %"PRIu64", refusing entry.", ts->monotonic);
+ return -EBADMSG;
+ }
+ } else {
dual_timestamp_get(&_ts);
ts = &_ts;
}
@@ -1983,7 +1982,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
#endif
/* alloca() can't take 0, hence let's allocate at least one */
- items = alloca(sizeof(EntryItem) * MAX(1u, n_iovec));
+ items = newa(EntryItem, MAX(1u, n_iovec));
for (i = 0; i < n_iovec; i++) {
uint64_t p;
@@ -2002,7 +2001,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
* times for rotating media. */
qsort_safe(items, n_iovec, sizeof(EntryItem), entry_item_cmp);
- r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqnum, ret, offset);
+ r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, ret, offset);
/* If the memory mapping triggered a SIGBUS then we return an
* IO error and ignore the error code passed down to us, since
@@ -3211,6 +3210,7 @@ int journal_file_open(
int flags,
mode_t mode,
bool compress,
+ uint64_t compress_threshold_bytes,
bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
@@ -3222,6 +3222,7 @@ int journal_file_open(
JournalFile *f;
void *h;
int r;
+ char bytes[FORMAT_BYTES_MAX];
assert(ret);
assert(fd >= 0 || fname);
@@ -3247,10 +3248,20 @@ int journal_file_open(
#elif HAVE_XZ
f->compress_xz = compress;
#endif
+
+ if (compress_threshold_bytes == (uint64_t) -1)
+ f->compress_threshold_bytes = DEFAULT_COMPRESS_THRESHOLD;
+ else
+ f->compress_threshold_bytes = MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes);
+
#if HAVE_GCRYPT
f->seal = seal;
#endif
+ log_debug("Journal effective settings seal=%s compress=%s compress_threshold_bytes=%s",
+ yes_no(f->seal), yes_no(JOURNAL_FILE_COMPRESS(f)),
+ format_bytes(bytes, sizeof(bytes), f->compress_threshold_bytes));
+
if (mmap_cache)
f->mmap = mmap_cache_ref(mmap_cache);
else {
@@ -3435,7 +3446,7 @@ fail:
return r;
}
-int journal_file_rotate(JournalFile **f, bool compress, bool seal, Set *deferred_closes) {
+int journal_file_rotate(JournalFile **f, bool compress, uint64_t compress_threshold_bytes, bool seal, Set *deferred_closes) {
_cleanup_free_ char *p = NULL;
size_t l;
JournalFile *old_file, *new_file = NULL;
@@ -3489,7 +3500,9 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal, Set *deferred
* we archive them */
old_file->defrag_on_close = true;
- r = journal_file_open(-1, old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, deferred_closes, old_file, &new_file);
+ r = journal_file_open(-1, old_file->path, old_file->flags, old_file->mode, compress,
+ compress_threshold_bytes, seal, NULL, old_file->mmap, deferred_closes,
+ old_file, &new_file);
if (deferred_closes &&
set_put(deferred_closes, old_file) >= 0)
@@ -3506,6 +3519,7 @@ int journal_file_open_reliably(
int flags,
mode_t mode,
bool compress,
+ uint64_t compress_threshold_bytes,
bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
@@ -3517,7 +3531,8 @@ int journal_file_open_reliably(
size_t l;
_cleanup_free_ char *p = NULL;
- r = journal_file_open(-1, fname, flags, mode, compress, seal, metrics, mmap_cache, deferred_closes, template, ret);
+ r = journal_file_open(-1, fname, flags, mode, compress, compress_threshold_bytes, seal, metrics, mmap_cache,
+ deferred_closes, template, ret);
if (!IN_SET(r,
-EBADMSG, /* Corrupted */
-ENODATA, /* Truncated */
@@ -3559,15 +3574,17 @@ int journal_file_open_reliably(
log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname);
- return journal_file_open(-1, fname, flags, mode, compress, seal, metrics, mmap_cache, deferred_closes, template, ret);
+ return journal_file_open(-1, fname, flags, mode, compress, compress_threshold_bytes, seal, metrics, mmap_cache,
+ deferred_closes, template, ret);
}
-int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) {
+int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p) {
uint64_t i, n;
uint64_t q, xor_hash = 0;
int r;
EntryItem *items;
dual_timestamp ts;
+ const sd_id128_t *boot_id;
assert(from);
assert(to);
@@ -3579,10 +3596,11 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
ts.monotonic = le64toh(o->entry.monotonic);
ts.realtime = le64toh(o->entry.realtime);
+ boot_id = &o->entry.boot_id;
n = journal_file_entry_n_items(o);
/* alloca() can't take 0, hence let's allocate at least one */
- items = alloca(sizeof(EntryItem) * MAX(1u, n));
+ items = newa(EntryItem, MAX(1u, n));
for (i = 0; i < n; i++) {
uint64_t l, h;
@@ -3638,7 +3656,8 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
return r;
}
- r = journal_file_append_entry_internal(to, &ts, xor_hash, items, n, seqnum, ret, offset);
+ r = journal_file_append_entry_internal(to, &ts, boot_id, xor_hash, items, n,
+ NULL, NULL, NULL);
if (mmap_cache_got_sigbus(to->mmap, to->cache_fd))
return -EIO;
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index 67abf8da49..c8114ee2d0 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#if HAVE_GCRYPT
@@ -90,8 +71,6 @@ typedef struct JournalFile {
bool close_fd:1;
bool archive:1;
- bool tail_entry_monotonic_valid:1;
-
direction_t last_direction;
LocationType location_type;
uint64_t last_n_entries;
@@ -124,6 +103,7 @@ typedef struct JournalFile {
unsigned last_seen_generation;
+ uint64_t compress_threshold_bytes;
#if HAVE_XZ || HAVE_LZ4
void *compress_buffer;
size_t compress_buffer_size;
@@ -153,6 +133,7 @@ int journal_file_open(
int flags,
mode_t mode,
bool compress,
+ uint64_t compress_threshold_bytes,
bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
@@ -169,6 +150,7 @@ int journal_file_open_reliably(
int flags,
mode_t mode,
bool compress,
+ uint64_t compress_threshold_bytes,
bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
@@ -217,7 +199,14 @@ uint64_t journal_file_entry_array_n_items(Object *o) _pure_;
uint64_t journal_file_hash_table_n_items(Object *o) _pure_;
int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset);
-int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset);
+int journal_file_append_entry(
+ JournalFile *f,
+ const dual_timestamp *ts,
+ const sd_id128_t *boot_id,
+ const struct iovec iovec[], unsigned n_iovec,
+ uint64_t *seqno,
+ Object **ret,
+ uint64_t *offset);
int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset);
int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset);
@@ -241,12 +230,12 @@ int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_
int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);
int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, uint64_t data_offset, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset);
-int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset);
+int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p);
void journal_file_dump(JournalFile *f);
void journal_file_print_header(JournalFile *f);
-int journal_file_rotate(JournalFile **f, bool compress, bool seal, Set *deferred_closes);
+int journal_file_rotate(JournalFile **f, bool compress, uint64_t compress_threshold_bytes, bool seal, Set *deferred_closes);
void journal_file_post_change(JournalFile *f);
int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t);
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
index e5f563cced..80a69da4d8 100644
--- a/src/journal/journal-internal.h
+++ b/src/journal/journal-internal.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/journal/journal-qrcode.c b/src/journal/journal-qrcode.c
index 5a9dcaa525..35d6ec4593 100644
--- a/src/journal/journal-qrcode.c
+++ b/src/journal/journal-qrcode.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <qrencode.h>
diff --git a/src/journal/journal-qrcode.h b/src/journal/journal-qrcode.h
index cb26754ada..0774608edf 100644
--- a/src/journal/journal-qrcode.h
+++ b/src/journal/journal-qrcode.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stdio.h>
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index 73329ba024..a0621524a9 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -441,9 +423,7 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
if (r < 0)
return r;
- r = fd;
- fd = -1;
- return r;
+ return TAKE_FD(fd);
}
_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
@@ -533,7 +513,7 @@ _public_ int sd_journal_sendv_with_location(
assert_return(iov, -EINVAL);
assert_return(n > 0, -EINVAL);
- niov = alloca(sizeof(struct iovec) * (n + 3));
+ niov = newa(struct iovec, n + 3);
memcpy(niov, iov, sizeof(struct iovec) * n);
ALLOCA_CODE_FUNC(f, func);
diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
index db36a6ab80..8d3ae71440 100644
--- a/src/journal/journal-vacuum.c
+++ b/src/journal/journal-vacuum.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <sys/stat.h>
@@ -299,7 +281,7 @@ int journal_directory_vacuum(
goto finish;
}
- list[n_list].filename = p;
+ list[n_list].filename = TAKE_PTR(p);
list[n_list].usage = size;
list[n_list].seqnum = seqnum;
list[n_list].realtime = realtime;
@@ -307,7 +289,6 @@ int journal_directory_vacuum(
list[n_list].have_seqnum = have_seqnum;
n_list++;
- p = NULL;
sum += size;
}
diff --git a/src/journal/journal-vacuum.h b/src/journal/journal-vacuum.h
index 2aec412385..0b336ac013 100644
--- a/src/journal/journal-vacuum.h
+++ b/src/journal/journal-vacuum.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stdbool.h>
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index 4d35168591..c2f0467c6e 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stddef.h>
diff --git a/src/journal/journal-verify.h b/src/journal/journal-verify.h
index 4f999154f1..f0ea31abc1 100644
--- a/src/journal/journal-verify.h
+++ b/src/journal/journal-verify.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "journal-file.h"
int journal_file_verify(JournalFile *f, const char *key, usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress);
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index e0ad0e1d11..56b1be530d 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -71,11 +53,12 @@
#include "rlimit-util.h"
#include "set.h"
#include "sigbus.h"
+#include "string-table.h"
#include "strv.h"
#include "syslog-util.h"
#include "terminal-util.h"
-#include "udev.h"
#include "udev-util.h"
+#include "udev.h"
#include "unit-name.h"
#include "user-util.h"
@@ -194,11 +177,11 @@ typedef struct BootId {
} BootId;
static int add_matches_for_device(sd_journal *j, const char *devpath) {
- int r;
- _cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
struct udev_device *d = NULL;
struct stat st;
+ int r;
assert(j);
assert(devpath);
@@ -212,14 +195,14 @@ static int add_matches_for_device(sd_journal *j, const char *devpath) {
if (!udev)
return log_oom();
- r = stat(devpath, &st);
- if (r < 0)
- log_error_errno(errno, "Couldn't stat file: %m");
+ if (stat(devpath, &st) < 0)
+ return log_error_errno(errno, "Couldn't stat file: %m");
- d = device = udev_device_new_from_devnum(udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
- if (!device)
- return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
+ r = udev_device_new_from_stat_rdev(udev, &st, &device);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
+ d = device;
while (d) {
_cleanup_free_ char *match = NULL;
const char *subsys, *sysname, *devnode;
@@ -316,7 +299,7 @@ static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset
static void help(void) {
- pager_open(arg_no_pager, arg_pager_end);
+ (void) pager_open(arg_no_pager, arg_pager_end);
printf("%s [OPTIONS...] [MATCHES...]\n\n"
"Query the journal.\n\n"
@@ -346,7 +329,7 @@ static void help(void) {
" -o --output=STRING Change journal output mode (short, short-precise,\n"
" short-iso, short-iso-precise, short-full,\n"
" short-monotonic, short-unix, verbose, export,\n"
- " json, json-pretty, json-sse, cat)\n"
+ " json, json-pretty, json-sse, cat, with-unit)\n"
" --output-fields=LIST Select fields to print in verbose/export/json modes\n"
" --utc Express time in Coordinated Universal Time (UTC)\n"
" -x --catalog Add message explanations where available\n"
@@ -522,6 +505,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output format '%s'.", optarg);
@@ -729,7 +717,6 @@ static int parse_argv(int argc, char *argv[]) {
arg_action = ACTION_SETUP_KEYS;
break;
-
case ARG_VERIFY_KEY:
arg_action = ACTION_VERIFY;
r = free_and_strdup(&arg_verify_key, optarg);
@@ -921,10 +908,9 @@ static int parse_argv(int argc, char *argv[]) {
if (!v)
return log_oom();
- if (!arg_output_fields) {
- arg_output_fields = v;
- v = NULL;
- } else {
+ if (!arg_output_fields)
+ arg_output_fields = TAKE_PTR(v);
+ else {
r = strv_extend_strv(&arg_output_fields, v, true);
if (r < 0)
return log_oom();
@@ -983,7 +969,6 @@ static int parse_argv(int argc, char *argv[]) {
arg_system_units = strv_free(arg_system_units);
}
-
#if HAVE_PCRE2
if (arg_pattern) {
unsigned flags;
@@ -1070,7 +1055,7 @@ static int add_matches(sd_journal *j, char **args) {
_cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL;
struct stat st;
- r = chase_symlinks(*i, NULL, 0, &p);
+ r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p);
if (r < 0)
return log_error_errno(r, "Couldn't canonicalize path: %m");
@@ -1229,8 +1214,7 @@ static int discover_next_boot(sd_journal *j,
if (r < 0)
return r;
- *ret = next_boot;
- next_boot = NULL;
+ *ret = TAKE_PTR(next_boot);
return 0;
}
@@ -1342,8 +1326,7 @@ static int get_boots(
}
}
LIST_INSERT_AFTER(boot_list, head, tail, current);
- tail = current;
- current = NULL;
+ tail = TAKE_PTR(current);
count++;
}
}
@@ -1369,7 +1352,7 @@ static int list_boots(sd_journal *j) {
if (count == 0)
return count;
- pager_open(arg_no_pager, arg_pager_end);
+ (void) pager_open(arg_no_pager, arg_pager_end);
/* numbers are one less, but we need an extra char for the sign */
w = DECIMAL_STR_WIDTH(count - 1) + 1;
@@ -1508,8 +1491,8 @@ static int get_possible_units(
}
}
- *units = found;
- found = NULL;
+ *units = TAKE_PTR(found);
+
return 0;
}
@@ -1539,7 +1522,7 @@ static int add_units(sd_journal *j) {
STRV_FOREACH(i, arg_system_units) {
_cleanup_free_ char *u = NULL;
- r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u);
+ r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u);
if (r < 0)
return r;
@@ -1584,7 +1567,7 @@ static int add_units(sd_journal *j) {
STRV_FOREACH(i, arg_user_units) {
_cleanup_free_ char *u = NULL;
- r = unit_name_mangle(*i, UNIT_NAME_GLOB, &u);
+ r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u);
if (r < 0)
return r;
@@ -1660,7 +1643,6 @@ static int add_priorities(sd_journal *j) {
return 0;
}
-
static int add_syslog_identifier(sd_journal *j) {
int r;
char **i;
@@ -2135,7 +2117,7 @@ int main(int argc, char *argv[]) {
} else {
bool oneline = arg_action == ACTION_LIST_CATALOG;
- pager_open(arg_no_pager, arg_pager_end);
+ (void) pager_open(arg_no_pager, arg_pager_end);
if (optind < argc)
r = catalog_list_items(stdout, database, oneline, argv + optind);
@@ -2410,11 +2392,13 @@ int main(int argc, char *argv[]) {
/* Opening the fd now means the first sd_journal_wait() will actually wait */
if (arg_follow) {
r = sd_journal_get_fd(j);
- if (r == -EMEDIUMTYPE) {
+ if (r == -EMFILE) {
+ log_warning("Insufficent watch descriptors available. Reverting to -n.");
+ arg_follow = false;
+ } else if (r == -EMEDIUMTYPE) {
log_error_errno(r, "The --follow switch is not supported in conjunction with reading from STDIN.");
goto finish;
- }
- if (r < 0) {
+ } else if (r < 0) {
log_error_errno(r, "Failed to get journal fd: %m");
goto finish;
}
@@ -2492,7 +2476,7 @@ int main(int argc, char *argv[]) {
need_seek = true;
if (!arg_follow)
- pager_open(arg_no_pager, arg_pager_end);
+ (void) pager_open(arg_no_pager, arg_pager_end);
if (!arg_quiet && (arg_lines != 0 || arg_follow)) {
usec_t start, end;
@@ -2632,8 +2616,8 @@ int main(int argc, char *argv[]) {
arg_utc * OUTPUT_UTC |
arg_no_hostname * OUTPUT_NO_HOSTNAME;
- r = output_journal(stdout, j, arg_output, 0, flags,
- arg_output_fields, highlight, &ellipsized);
+ r = show_journal_entry(stdout, j, arg_output, 0, flags,
+ arg_output_fields, highlight, &ellipsized);
need_seek = true;
if (r == -EADDRNOTAVAIL)
break;
diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c
index 19f53751cb..87726684af 100644
--- a/src/journal/journald-audit.c
+++ b/src/journal/journald-audit.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "audit-type.h"
@@ -339,7 +321,7 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s
char id_field[sizeof("_AUDIT_ID=") + DECIMAL_STR_MAX(uint64_t)],
type_field[sizeof("_AUDIT_TYPE=") + DECIMAL_STR_MAX(int)],
source_time_field[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)];
- char *m;
+ char *m, *type_field_name;
int k;
assert(s);
@@ -372,7 +354,7 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s
if (isempty(p))
return;
- n_iov_allocated = N_IOVEC_META_FIELDS + 7;
+ n_iov_allocated = N_IOVEC_META_FIELDS + 8;
iov = new(struct iovec, n_iov_allocated);
if (!iov) {
log_oom();
@@ -397,6 +379,9 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s
type_name = audit_type_name_alloca(type);
+ type_field_name = strjoina("_AUDIT_TYPE_NAME=", type_name);
+ iov[n_iov++] = IOVEC_MAKE_STRING(type_field_name);
+
m = strjoina("MESSAGE=", type_name, " ", p);
iov[n_iov++] = IOVEC_MAKE_STRING(m);
@@ -459,8 +444,8 @@ void server_process_audit_message(
if (IN_SET(nl->nlmsg_type, NLMSG_NOOP, NLMSG_ERROR))
return;
- /* Below AUDIT_FIRST_USER_MSG theer are only control messages, let's ignore those */
- if (nl->nlmsg_type < AUDIT_FIRST_USER_MSG)
+ /* Except AUDIT_USER, all messsages below AUDIT_FIRST_USER_MSG are control messages, let's ignore those */
+ if (nl->nlmsg_type < AUDIT_FIRST_USER_MSG && nl->nlmsg_type != AUDIT_USER)
return;
process_audit_string(s, nl->nlmsg_type, NLMSG_DATA(nl), nl->nlmsg_len - ALIGN(sizeof(struct nlmsghdr)));
diff --git a/src/journal/journald-audit.h b/src/journal/journald-audit.h
index 83dd4bca7a..57bb1711c9 100644
--- a/src/journal/journald-audit.h
+++ b/src/journal/journald-audit.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "journald-server.h"
#include "socket-util.h"
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
index 98fbb83a0c..80e2958597 100644
--- a/src/journal/journald-console.c
+++ b/src/journal/journald-console.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <sys/socket.h>
diff --git a/src/journal/journald-console.h b/src/journal/journald-console.h
index 3b345507d9..3def00ad5d 100644
--- a/src/journal/journald-console.h
+++ b/src/journal/journald-console.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "journald-server.h"
void server_forward_console(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred);
diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c
index f5345e4cb2..ce07de1bfb 100644
--- a/src/journal/journald-context.c
+++ b/src/journal/journald-context.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#if HAVE_SELINUX
#include <selinux/selinux.h>
@@ -439,14 +421,11 @@ static int client_context_read_extra_fields(
free(c->extra_fields_iovec);
free(c->extra_fields_data);
- c->extra_fields_iovec = iovec;
+ c->extra_fields_iovec = TAKE_PTR(iovec);
c->extra_fields_n_iovec = n_iovec;
- c->extra_fields_data = data;
+ c->extra_fields_data = TAKE_PTR(data);
c->extra_fields_mtime = timespec_load_nsec(&st.st_mtim);
- iovec = NULL;
- data = NULL;
-
return 0;
}
diff --git a/src/journal/journald-context.h b/src/journal/journald-context.h
index e29f59ce5d..9df3a38eff 100644
--- a/src/journal/journald-context.h
+++ b/src/journal/journald-context.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf
index e8c1f2e2d5..1adcb50b6d 100644
--- a/src/journal/journald-gperf.gperf
+++ b/src/journal/journald-gperf.gperf
@@ -19,7 +19,7 @@ struct ConfigPerfItem;
%includes
%%
Journal.Storage, config_parse_storage, 0, offsetof(Server, storage)
-Journal.Compress, config_parse_bool, 0, offsetof(Server, compress)
+Journal.Compress, config_parse_compress, 0, offsetof(Server, compress)
Journal.Seal, config_parse_bool, 0, offsetof(Server, seal)
Journal.ReadKMsg, config_parse_bool, 0, offsetof(Server, read_kmsg)
Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec)
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index 5895e48701..e9aff13168 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <sys/epoll.h>
diff --git a/src/journal/journald-kmsg.h b/src/journal/journald-kmsg.h
index af795eaf63..bff24ac310 100644
--- a/src/journal/journald-kmsg.h
+++ b/src/journal/journald-kmsg.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "journald-server.h"
int server_open_dev_kmsg(Server *s);
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
index cee873215d..5ff22a10af 100644
--- a/src/journal/journald-native.c
+++ b/src/journal/journald-native.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
#include <sys/epoll.h>
@@ -343,20 +325,15 @@ void server_process_native_file(
sealed = memfd_get_sealed(fd) > 0;
if (!sealed && (!ucred || ucred->uid != 0)) {
- _cleanup_free_ char *sl = NULL, *k = NULL;
+ _cleanup_free_ char *k = NULL;
const char *e;
/* If this is not a sealed memfd, and the peer is unknown or
* unprivileged, then verify the path. */
- if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
- log_oom();
- return;
- }
-
- r = readlink_malloc(sl, &k);
+ r = fd_get_path(fd, &k);
if (r < 0) {
- log_error_errno(r, "readlink(%s) failed: %m", sl);
+ log_error_errno(r, "readlink(/proc/self/fd/%i) failed: %m", fd);
return;
}
diff --git a/src/journal/journald-native.h b/src/journal/journald-native.h
index f1b4abc41a..7211d4fab4 100644
--- a/src/journal/journald-native.h
+++ b/src/journal/journald-native.h
@@ -1,29 +1,23 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "journald-server.h"
-void server_process_native_message(Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len);
-
-void server_process_native_file(Server *s, int fd, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len);
-
-int server_open_native_socket(Server*s);
+void server_process_native_message(
+ Server *s,
+ const void *buffer,
+ size_t buffer_size,
+ const struct ucred *ucred,
+ const struct timeval *tv,
+ const char *label,
+ size_t label_len);
+
+void server_process_native_file(
+ Server *s,
+ int fd,
+ const struct ucred *ucred,
+ const struct timeval *tv,
+ const char *label,
+ size_t label_len);
+
+int server_open_native_socket(Server *s);
diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c
index 3517ce2e1c..6a8a36a736 100644
--- a/src/journal/journald-rate-limit.c
+++ b/src/journal/journald-rate-limit.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
diff --git a/src/journal/journald-rate-limit.h b/src/journal/journald-rate-limit.h
index af7bb495f2..3a7f106de0 100644
--- a/src/journal/journald-rate-limit.h
+++ b/src/journal/journald-rate-limit.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "util.h"
typedef struct JournalRateLimit JournalRateLimit;
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 5cd58e8a77..4f1550ec5b 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#if HAVE_SELINUX
#include <selinux/selinux.h>
@@ -79,7 +61,7 @@
#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
-#define DEFAULT_RATE_LIMIT_BURST 1000
+#define DEFAULT_RATE_LIMIT_BURST 10000
#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH
#define RECHECK_SPACE_USEC (30*USEC_PER_SEC)
@@ -180,7 +162,6 @@ static void patch_min_use(JournalStorage *storage) {
storage->metrics.min_use = MAX(storage->metrics.min_use, storage->space.vfs_used);
}
-
static int determine_space(Server *s, uint64_t *available, uint64_t *limit) {
JournalStorage *js;
int r;
@@ -280,9 +261,12 @@ static int open_journal(
assert(ret);
if (reliably)
- r = journal_file_open_reliably(fname, flags, 0640, s->compress, seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
+ r = journal_file_open_reliably(fname, flags, 0640, s->compress.enabled, s->compress.threshold_bytes,
+ seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
else
- r = journal_file_open(-1, fname, flags, 0640, s->compress, seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
+ r = journal_file_open(-1, fname, flags, 0640, s->compress.enabled, s->compress.threshold_bytes, seal,
+ metrics, s->mmap, s->deferred_closes, NULL, &f);
+
if (r < 0)
return r;
@@ -463,7 +447,7 @@ static int do_rotate(
if (!*f)
return -EINVAL;
- r = journal_file_rotate(f, s->compress, seal, s->deferred_closes);
+ r = journal_file_rotate(f, s->compress.enabled, s->compress.threshold_bytes, seal, s->deferred_closes);
if (r < 0) {
if (*f)
return log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
@@ -655,7 +639,7 @@ static bool shall_try_append_again(JournalFile *f, int r) {
}
}
-static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) {
+static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n, int priority) {
bool vacuumed = false, rotate = false;
struct dual_timestamp ts;
JournalFile *f;
@@ -703,14 +687,14 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned
s->last_realtime_clock = ts.realtime;
- r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL);
+ r = journal_file_append_entry(f, &ts, NULL, iovec, n, &s->seqnum, NULL, NULL);
if (r >= 0) {
server_schedule_sync(s, priority);
return;
}
if (vacuumed || !shall_try_append_again(f, r)) {
- log_error_errno(r, "Failed to write entry (%d items, %zu bytes), ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
+ log_error_errno(r, "Failed to write entry (%zu items, %zu bytes), ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
return;
}
@@ -722,9 +706,9 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned
return;
log_debug("Retrying write.");
- r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL);
+ r = journal_file_append_entry(f, &ts, NULL, iovec, n, &s->seqnum, NULL, NULL);
if (r < 0)
- log_error_errno(r, "Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
+ log_error_errno(r, "Failed to write entry (%zu items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
else
server_schedule_sync(s, priority);
}
@@ -1023,7 +1007,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
goto finish;
}
- r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
+ r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset);
if (r >= 0)
continue;
@@ -1042,7 +1026,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
}
log_debug("Retrying write.");
- r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
+ r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset);
if (r < 0) {
log_error_errno(r, "Can't write entry: %m");
goto finish;
@@ -1080,7 +1064,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
struct iovec iovec;
ssize_t n;
int *fds = NULL, v = 0;
- unsigned n_fds = 0;
+ size_t n_fds = 0;
union {
struct cmsghdr cmsghdr;
@@ -1166,7 +1150,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
if (fd == s->syslog_fd) {
if (n > 0 && n_fds == 0)
- server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
+ server_process_syslog_message(s, s->buffer, n, ucred, tv, label, label_len);
else if (n_fds > 0)
log_warning("Got file descriptors via syslog socket. Ignoring.");
@@ -1695,7 +1679,8 @@ int server_init(Server *s) {
zero(*s);
s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = s->notify_fd = -1;
- s->compress = true;
+ s->compress.enabled = true;
+ s->compress.threshold_bytes = (uint64_t) -1;
s->seal = true;
s->read_kmsg = true;
@@ -2038,3 +2023,37 @@ int config_parse_line_max(
return 0;
}
+
+int config_parse_compress(const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ JournalCompressOptions* compress = data;
+ int r;
+
+ if (streq(rvalue, "1")) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Compress= ambiguously specified as 1, enabling compression with default threshold");
+ compress->enabled = true;
+ } else if (streq(rvalue, "0")) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Compress= ambiguously specified as 0, disabling compression");
+ compress->enabled = false;
+ } else if ((r = parse_boolean(rvalue)) >= 0)
+ compress->enabled = r;
+ else if (parse_size(rvalue, 1024, &compress->threshold_bytes) == 0)
+ compress->enabled = true;
+ else if (isempty(rvalue)) {
+ compress->enabled = true;
+ compress->threshold_bytes = (uint64_t) -1;
+ } else
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Compress= value, ignoring: %s", rvalue);
+
+ return 0;
+}
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index bf4ba6897a..983be8bb89 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
@@ -27,6 +8,7 @@
typedef struct Server Server;
+#include "conf-parser.h"
#include "hashmap.h"
#include "journal-file.h"
#include "journald-context.h"
@@ -52,6 +34,11 @@ typedef enum SplitMode {
_SPLIT_INVALID = -1
} SplitMode;
+typedef struct JournalCompressOptions {
+ bool enabled;
+ uint64_t threshold_bytes;
+} JournalCompressOptions;
+
typedef struct JournalStorageSpace {
usec_t timestamp;
@@ -113,7 +100,7 @@ struct Server {
JournalStorage runtime_storage;
JournalStorage system_storage;
- bool compress;
+ JournalCompressOptions compress;
bool seal;
bool read_kmsg;
@@ -203,13 +190,14 @@ void server_driver_message(Server *s, pid_t object_pid, const char *message_id,
/* gperf lookup function */
const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-int config_parse_storage(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_line_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_storage);
+CONFIG_PARSER_PROTOTYPE(config_parse_line_max);
+CONFIG_PARSER_PROTOTYPE(config_parse_compress);
const char *storage_to_string(Storage s) _const_;
Storage storage_from_string(const char *s) _pure_;
-int config_parse_split_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_split_mode);
const char *split_mode_to_string(SplitMode s) _const_;
SplitMode split_mode_from_string(const char *s) _pure_;
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index bb7330f3db..dbf3503a82 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
#include <unistd.h>
@@ -391,7 +373,7 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
return -EINVAL;
}
- s->level_prefix = !!r;
+ s->level_prefix = r;
s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
return 0;
@@ -402,7 +384,7 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
return -EINVAL;
}
- s->forward_to_syslog = !!r;
+ s->forward_to_syslog = r;
s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
return 0;
@@ -413,7 +395,7 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
return -EINVAL;
}
- s->forward_to_kmsg = !!r;
+ s->forward_to_kmsg = r;
s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
return 0;
@@ -424,7 +406,7 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
return -EINVAL;
}
- s->forward_to_console = !!r;
+ s->forward_to_console = r;
s->state = STDOUT_STREAM_RUNNING;
/* Try to save the stream, so that journald can be restarted and we can recover */
@@ -659,7 +641,7 @@ static int stdout_stream_load(StdoutStream *stream, const char *fname) {
return log_oom();
}
- r = parse_env_file(stream->state_file, NEWLINE,
+ r = parse_env_file(NULL, stream->state_file, NEWLINE,
"PRIORITY", &priority,
"LEVEL_PREFIX", &level_prefix,
"FORWARD_TO_SYSLOG", &forward_to_syslog,
@@ -779,8 +761,8 @@ int server_restore_streams(Server *s, FDSet *fds) {
/* No file descriptor? Then let's delete the state file */
log_debug("Cannot restore stream file %s", de->d_name);
if (unlinkat(dirfd(d), de->d_name, 0) < 0)
- log_warning("Failed to remove /run/systemd/journal/streams/%s: %m",
- de->d_name);
+ log_warning_errno(errno, "Failed to remove /run/systemd/journal/streams/%s: %m",
+ de->d_name);
continue;
}
diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h
index fd220b5864..bc5622ab3b 100644
--- a/src/journal/journald-stream.h
+++ b/src/journal/journald-stream.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct StdoutStream StdoutStream;
#include "fdset.h"
diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
index 4018288b0c..9dea116722 100644
--- a/src/journal/journald-syslog.c
+++ b/src/journal/journald-syslog.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
#include <sys/epoll.h>
@@ -116,7 +98,7 @@ static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned
log_debug_errno(errno, "Failed to forward syslog message: %m");
}
-static void forward_syslog_raw(Server *s, int priority, const char *buffer, const struct ucred *ucred, const struct timeval *tv) {
+static void forward_syslog_raw(Server *s, int priority, const char *buffer, size_t buffer_len, const struct ucred *ucred, const struct timeval *tv) {
struct iovec iovec;
assert(s);
@@ -125,7 +107,7 @@ static void forward_syslog_raw(Server *s, int priority, const char *buffer, cons
if (LOG_PRI(priority) > s->max_level_syslog)
return;
- iovec = IOVEC_MAKE_STRING(buffer);
+ iovec = IOVEC_MAKE((char *) buffer, buffer_len);
forward_syslog_iovec(s, &iovec, 1, ucred, tv);
}
@@ -315,20 +297,20 @@ static void syslog_skip_date(char **buf) {
void server_process_syslog_message(
Server *s,
const char *buf,
+ size_t buf_len,
const struct ucred *ucred,
const struct timeval *tv,
const char *label,
size_t label_len) {
char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)],
- syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
+ syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)], *msg;
const char *message = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
_cleanup_free_ char *identifier = NULL, *pid = NULL;
int priority = LOG_USER | LOG_INFO, r;
ClientContext *context = NULL;
struct iovec *iovec;
- const char *orig;
- size_t n = 0, m;
+ size_t n = 0, m, i;
assert(s);
assert(buf);
@@ -339,26 +321,35 @@ void server_process_syslog_message(
log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid);
}
- orig = buf;
- syslog_parse_priority(&buf, &priority, true);
+ /* We are creating copy of the message because we want to forward original message verbatim to the legacy
+ syslog implementation */
+ for (i = buf_len; i > 0; i--)
+ if (!strchr(WHITESPACE, buf[i-1]))
+ break;
+
+ msg = newa(char, i + 1);
+ *((char *) mempcpy(msg, buf, i)) = 0;
+ msg = skip_leading_chars(msg, WHITESPACE);
+
+ syslog_parse_priority((const char **)&msg, &priority, true);
if (!client_context_test_priority(context, priority))
return;
if (s->forward_to_syslog)
- forward_syslog_raw(s, priority, orig, ucred, tv);
+ forward_syslog_raw(s, priority, buf, buf_len, ucred, tv);
- syslog_skip_date((char**) &buf);
- syslog_parse_identifier(&buf, &identifier, &pid);
+ syslog_skip_date(&msg);
+ syslog_parse_identifier((const char**)&msg, &identifier, &pid);
if (s->forward_to_kmsg)
- server_forward_kmsg(s, priority, identifier, buf, ucred);
+ server_forward_kmsg(s, priority, identifier, msg, ucred);
if (s->forward_to_console)
- server_forward_console(s, priority, identifier, buf, ucred);
+ server_forward_console(s, priority, identifier, msg, ucred);
if (s->forward_to_wall)
- server_forward_wall(s, priority, identifier, buf, ucred);
+ server_forward_wall(s, priority, identifier, msg, ucred);
m = N_IOVEC_META_FIELDS + 6 + client_context_extra_fields_n_iovec(context);
iovec = newa(struct iovec, m);
@@ -383,7 +374,7 @@ void server_process_syslog_message(
iovec[n++] = IOVEC_MAKE_STRING(syslog_pid);
}
- message = strjoina("MESSAGE=", buf);
+ message = strjoina("MESSAGE=", msg);
if (message)
iovec[n++] = IOVEC_MAKE_STRING(message);
diff --git a/src/journal/journald-syslog.h b/src/journal/journald-syslog.h
index 3438107c5f..7ca5897264 100644
--- a/src/journal/journald-syslog.h
+++ b/src/journal/journald-syslog.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "journald-server.h"
int syslog_fixup_facility(int priority) _const_;
@@ -28,7 +9,7 @@ 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, const struct ucred *ucred, const struct timeval *tv);
-void server_process_syslog_message(Server *s, const char *buf, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len);
+void server_process_syslog_message(Server *s, const char *buf, size_t buf_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len);
int server_open_syslog_socket(Server *s);
void server_maybe_warn_forward_syslog_missed(Server *s);
diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c
index 431abfeb32..75328aa94b 100644
--- a/src/journal/journald-wall.c
+++ b/src/journal/journald-wall.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Sebastian Thorarensen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Sebastian Thorarensen
***/
#include "alloc-util.h"
diff --git a/src/journal/journald-wall.h b/src/journal/journald-wall.h
index 46ceac26bb..be27370d6b 100644
--- a/src/journal/journald-wall.h
+++ b/src/journal/journald-wall.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Sebastian Thorarensen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Sebastian Thorarensen
***/
#include "journald-server.h"
diff --git a/src/journal/journald.c b/src/journal/journald.c
index 10a6955769..5e7b1dcb4a 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
diff --git a/src/journal/journald.conf b/src/journal/journald.conf
index 03fce40e90..94d5c678aa 100644
--- a/src/journal/journald.conf
+++ b/src/journal/journald.conf
@@ -18,7 +18,7 @@
#SplitMode=uid
#SyncIntervalSec=5m
#RateLimitIntervalSec=30s
-#RateLimitBurst=1000
+#RateLimitBurst=10000
#SystemMaxUse=
#SystemKeepFree=
#SystemMaxFileSize=
diff --git a/src/journal/lookup3.c b/src/journal/lookup3.c
index ec725ce46c..ff194dd951 100644
--- a/src/journal/lookup3.c
+++ b/src/journal/lookup3.c
@@ -214,7 +214,6 @@ uint32_t initval) /* the previous hash, or an arbitrary value */
return c;
}
-
/*
--------------------------------------------------------------------
hashword2() -- same as hashword(), but take two seeds and return two
@@ -260,7 +259,6 @@ uint32_t *pb) /* IN: more seed OUT: secondary hash value */
*pc=c; *pb=b;
}
-
/*
-------------------------------------------------------------------------------
hashlittle() -- hash a variable-length key into a 32-bit value
@@ -317,11 +315,11 @@ uint32_t jenkins_hashlittle( const void *key, size_t length, uint32_t initval)
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
+#if !VALGRIND && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
@@ -458,7 +456,6 @@ uint32_t jenkins_hashlittle( const void *key, size_t length, uint32_t initval)
return c;
}
-
/*
* hashlittle2: return 2 32-bit hash values
*
@@ -503,11 +500,11 @@ void jenkins_hashlittle2(
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
+#if !VALGRIND && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
@@ -644,8 +641,6 @@ void jenkins_hashlittle2(
*pc=c; *pb=b;
}
-
-
/*
* hashbig():
* This is the same as hashword() on big-endian machines. It is different
@@ -681,11 +676,11 @@ uint32_t jenkins_hashbig( const void *key, size_t length, uint32_t initval)
* then shifts out the part it's not allowed to read. Because the
* string is aligned, the illegal read is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
+#if !VALGRIND && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
@@ -775,7 +770,6 @@ uint32_t jenkins_hashbig( const void *key, size_t length, uint32_t initval)
return c;
}
-
#ifdef SELF_TEST
/* used for timings */
@@ -967,7 +961,6 @@ void driver3()
uint8_t buf[1];
uint32_t h,i,state[HASHSTATE];
-
buf[0] = ~0;
for (i=0; i<HASHSTATE; ++i) state[i] = 1;
printf("These should all be different\n");
@@ -999,7 +992,6 @@ void driver5()
printf("hash is %.8lx\n", c); /* cd628161 */
}
-
int main()
{
driver1(); /* test that the key is hashed: used for timings */
diff --git a/src/journal/meson.build b/src/journal/meson.build
index db4d598e72..807dece545 100644
--- a/src/journal/meson.build
+++ b/src/journal/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
journal_client_sources = files('''
audit-type.c
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
index 630ae6fbac..2366055f0a 100644
--- a/src/journal/mmap-cache.c
+++ b/src/journal/mmap-cache.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
@@ -220,8 +202,7 @@ static void context_detach_window(Context *c) {
if (!c->window)
return;
- w = c->window;
- c->window = NULL;
+ w = TAKE_PTR(c->window);
LIST_REMOVE(by_window, w->contexts, c);
if (!w->contexts && !w->keep_always) {
diff --git a/src/journal/mmap-cache.h b/src/journal/mmap-cache.h
index 00bcafdfb1..bf70d32027 100644
--- a/src/journal/mmap-cache.h
+++ b/src/journal/mmap-cache.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/stat.h>
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 11dbd83f2d..83abd82d1c 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -1337,7 +1319,7 @@ static int add_any_file(
goto finish;
}
- r = journal_file_open(fd, path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, NULL, &f);
+ r = journal_file_open(fd, path, O_RDONLY, 0, false, 0, false, NULL, j->mmap, NULL, NULL, &f);
if (r < 0) {
log_debug_errno(r, "Failed to open journal file %s: %m", path);
goto finish;
@@ -1827,7 +1809,7 @@ static int allocate_inotify(sd_journal *j) {
}
static sd_journal *journal_new(int flags, const char *path) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
j = new0(sd_journal, 1);
if (!j)
@@ -1844,7 +1826,7 @@ static sd_journal *journal_new(int flags, const char *path) {
t = strdup(path);
if (!t)
- goto fail;
+ return NULL;
if (flags & SD_JOURNAL_OS_ROOT)
j->prefix = t;
@@ -1854,19 +1836,15 @@ static sd_journal *journal_new(int flags, const char *path) {
j->files = ordered_hashmap_new(&path_hash_ops);
if (!j->files)
- goto fail;
+ return NULL;
j->files_cache = ordered_hashmap_iterated_cache_new(j->files);
j->directories_by_path = hashmap_new(&path_hash_ops);
j->mmap = mmap_cache_new();
if (!j->files_cache || !j->directories_by_path || !j->mmap)
- goto fail;
-
- return j;
+ return NULL;
-fail:
- sd_journal_close(j);
- return NULL;
+ return TAKE_PTR(j);
}
#define OPEN_ALLOWED_FLAGS \
@@ -1875,7 +1853,7 @@ fail:
SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)
_public_ int sd_journal_open(sd_journal **ret, int flags) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
int r;
assert_return(ret, -EINVAL);
@@ -1887,15 +1865,10 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) {
r = add_search_paths(j);
if (r < 0)
- goto fail;
+ return r;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
-
- return r;
}
#define OPEN_CONTAINER_ALLOWED_FLAGS \
@@ -1903,7 +1876,7 @@ fail:
_public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
_cleanup_free_ char *root = NULL, *class = NULL;
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
char *p;
int r;
@@ -1916,7 +1889,7 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
assert_return(machine_name_is_valid(machine), -EINVAL);
p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "ROOT", &root, "CLASS", &class, NULL);
if (r == -ENOENT)
return -EHOSTDOWN;
if (r < 0)
@@ -1933,14 +1906,10 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
r = add_search_paths(j);
if (r < 0)
- goto fail;
+ return r;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
- return r;
}
#define OPEN_DIRECTORY_ALLOWED_FLAGS \
@@ -1948,7 +1917,7 @@ fail:
SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
int r;
assert_return(ret, -EINVAL);
@@ -1964,18 +1933,14 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
else
r = add_root_directory(j, path, false);
if (r < 0)
- goto fail;
+ return r;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
- return r;
}
_public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
const char **path;
int r;
@@ -1989,17 +1954,13 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
STRV_FOREACH(path, paths) {
r = add_any_file(j, -1, *path);
if (r < 0)
- goto fail;
+ return r;
}
j->no_new_files = true;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
- return r;
}
#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \
@@ -2007,7 +1968,7 @@ fail:
SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
struct stat st;
int r;
@@ -2032,20 +1993,16 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
else
r = add_root_directory(j, NULL, false);
if (r < 0)
- goto fail;
+ return r;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
- return r;
}
_public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) {
Iterator iterator;
JournalFile *f;
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
unsigned i;
int r;
@@ -2082,7 +2039,7 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd
j->no_new_files = true;
j->no_inotify = true;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
fail:
@@ -2091,7 +2048,6 @@ fail:
ORDERED_HASHMAP_FOREACH(f, j->files, iterator)
f->close_fd = false;
- sd_journal_close(j);
return r;
}
diff --git a/src/journal/test-audit-type.c b/src/journal/test-audit-type.c
index 0f9780380d..20e654b599 100644
--- a/src/journal/test-audit-type.c
+++ b/src/journal/test-audit-type.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 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 <linux/audit.h>
diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c
index 2ad9909d1b..8eae993780 100644
--- a/src/journal/test-catalog.c
+++ b/src/journal/test-catalog.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -29,6 +10,7 @@
#include "alloc-util.h"
#include "catalog.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
@@ -45,9 +27,8 @@ static const char *no_catalog_dirs[] = {
NULL
};
-static Hashmap * test_import(const char* contents, ssize_t size, int code) {
- int r;
- char name[] = "/tmp/test-catalog.XXXXXX";
+static Hashmap* test_import(const char* contents, ssize_t size, int code) {
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-catalog.XXXXXX";
_cleanup_close_ int fd;
Hashmap *h;
@@ -60,10 +41,7 @@ static Hashmap * test_import(const char* contents, ssize_t size, int code) {
assert_se(fd >= 0);
assert_se(write(fd, contents, size) == size);
- r = catalog_import_file(h, name);
- assert_se(r == code);
-
- unlink(name);
+ assert_se(catalog_import_file(h, name) == code);
return h;
}
@@ -177,29 +155,21 @@ static void test_catalog_import_merge_no_body(void) {
}
}
-static const char* database = NULL;
-
-static void test_catalog_update(void) {
- static char name[] = "/tmp/test-catalog.XXXXXX";
+static void test_catalog_update(const char *database) {
int r;
- r = mkostemp_safe(name);
- assert_se(r >= 0);
-
- database = name;
-
/* Test what happens if there are no files. */
r = catalog_update(database, NULL, NULL);
- assert_se(r >= 0);
+ assert_se(r == 0);
/* Test what happens if there are no files in the directory. */
r = catalog_update(database, NULL, no_catalog_dirs);
- assert_se(r >= 0);
+ assert_se(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_se(r >= 0);
+ assert_se(r == 0);
}
static void test_catalog_file_lang(void) {
@@ -231,6 +201,7 @@ static void test_catalog_file_lang(void) {
}
int main(int argc, char *argv[]) {
+ _cleanup_(unlink_tempfilep) char database[] = "/tmp/test-catalog.XXXXXX";
_cleanup_free_ char *text = NULL;
int r;
@@ -247,7 +218,9 @@ int main(int argc, char *argv[]) {
test_catalog_import_merge();
test_catalog_import_merge_no_body();
- test_catalog_update();
+ assert_se(mkostemp_safe(database) >= 0);
+
+ test_catalog_update(database);
r = catalog_list(stdout, database, true);
assert_se(r >= 0);
@@ -258,8 +231,5 @@ int main(int argc, char *argv[]) {
assert_se(catalog_get(database, SD_MESSAGE_COREDUMP, &text) >= 0);
printf(">>>%s<<<\n", text);
- if (database)
- unlink(database);
-
return 0;
}
diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c
index 1f77197549..411df3fa7a 100644
--- a/src/journal/test-compress-benchmark.c
+++ b/src/journal/test-compress-benchmark.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "compress.h"
@@ -150,7 +132,7 @@ static void test_compress_decompress(const char* label, const char* type,
dt = (n2-n) / 1e6;
log_info("%s/%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), "
- "mean compresion %.2f%%, skipped %zu bytes",
+ "mean compression %.2f%%, skipped %zu bytes",
label, type, total, dt,
total / 1024. / 1024 / dt,
100 - compressed * 100. / total,
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
index ea1ffcc4af..791c6fdffb 100644
--- a/src/journal/test-compress.c
+++ b/src/journal/test-compress.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#if HAVE_LZ4
#include <lz4.h>
@@ -26,6 +8,7 @@
#include "compress.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "macro.h"
#include "path-util.h"
#include "random-util.h"
@@ -155,8 +138,9 @@ static void test_compress_stream(int compression,
const char *srcfile) {
_cleanup_close_ int src = -1, dst = -1, dst2 = -1;
- char pattern[] = "/tmp/systemd-test.compressed.XXXXXX",
- pattern2[] = "/tmp/systemd-test.compressed.XXXXXX";
+ _cleanup_(unlink_tempfilep) char
+ pattern[] = "/tmp/systemd-test.compressed.XXXXXX",
+ pattern2[] = "/tmp/systemd-test.compressed.XXXXXX";
int r;
_cleanup_free_ char *cmd = NULL, *cmd2 = NULL;
struct stat st = {};
@@ -208,9 +192,6 @@ static void test_compress_stream(int compression,
assert_se(lseek(dst2, 0, SEEK_SET) == 0);
r = decompress(dst, dst2, st.st_size - 1);
assert_se(r == -EFBIG);
-
- assert_se(unlink(pattern) == 0);
- assert_se(unlink(pattern2) == 0);
}
#endif
diff --git a/src/journal/test-journal-config.c b/src/journal/test-journal-config.c
new file mode 100644
index 0000000000..1482490411
--- /dev/null
+++ b/src/journal/test-journal-config.c
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdbool.h>
+
+#include "journald-server.h"
+
+#define _COMPRESS_PARSE_CHECK(str, enab, thresh, varname) \
+ do { \
+ JournalCompressOptions varname = {true, 111}; \
+ config_parse_compress("", "", 0, "", 0, "", 0, str, \
+ &varname, NULL); \
+ assert_se((enab) == varname.enabled); \
+ if (varname.enabled) \
+ assert_se((thresh) == varname.threshold_bytes); \
+ } while (0)
+
+#define COMPRESS_PARSE_CHECK(str, enabled, threshold) \
+ _COMPRESS_PARSE_CHECK(str, enabled, threshold, conf##__COUNTER__)
+
+static void test_config_compress(void) {
+ COMPRESS_PARSE_CHECK("yes", true, 111);
+ COMPRESS_PARSE_CHECK("no", false, 111);
+ COMPRESS_PARSE_CHECK("y", true, 111);
+ COMPRESS_PARSE_CHECK("n", false, 111);
+ COMPRESS_PARSE_CHECK("true", true, 111);
+ COMPRESS_PARSE_CHECK("false", false, 111);
+ COMPRESS_PARSE_CHECK("t", true, 111);
+ COMPRESS_PARSE_CHECK("f", false, 111);
+ COMPRESS_PARSE_CHECK("on", true, 111);
+ COMPRESS_PARSE_CHECK("off", false, 111);
+
+ /* Weird size/bool overlapping case. We preserve backward compatibility instead of assuming these are byte
+ * counts. */
+ COMPRESS_PARSE_CHECK("1", true, 111);
+ COMPRESS_PARSE_CHECK("0", false, 111);
+
+ /* IEC sizing */
+ COMPRESS_PARSE_CHECK("1B", true, 1);
+ COMPRESS_PARSE_CHECK("1K", true, 1024);
+ COMPRESS_PARSE_CHECK("1M", true, 1024 * 1024);
+ COMPRESS_PARSE_CHECK("1G", true, 1024 * 1024 * 1024);
+
+ /* Invalid Case */
+ COMPRESS_PARSE_CHECK("-1", true, 111);
+ COMPRESS_PARSE_CHECK("blah blah", true, 111);
+ COMPRESS_PARSE_CHECK("", true, (uint64_t)-1);
+}
+
+int main(int argc, char *argv[]) {
+ test_config_compress();
+
+ return 0;
+}
diff --git a/src/journal/test-journal-enum.c b/src/journal/test-journal-enum.c
index 9733eec0e2..b25a983498 100644
--- a/src/journal/test-journal-enum.c
+++ b/src/journal/test-journal-enum.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c
index f9b7b75ef1..81dbc22a70 100644
--- a/src/journal/test-journal-flush.c
+++ b/src/journal/test-journal-flush.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
@@ -39,7 +21,7 @@ int main(int argc, char *argv[]) {
assert_se(mkdtemp(dn));
fn = strappend(dn, "/test.journal");
- r = journal_file_open(-1, fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, NULL, &new_journal);
+ r = journal_file_open(-1, fn, O_CREAT|O_RDWR, 0644, false, 0, false, NULL, NULL, NULL, NULL, &new_journal);
assert_se(r >= 0);
r = sd_journal_open(&j, 0);
@@ -57,7 +39,7 @@ int main(int argc, char *argv[]) {
r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
assert_se(r >= 0);
- r = journal_file_copy_entry(f, new_journal, o, f->current_offset, NULL, NULL, NULL);
+ r = journal_file_copy_entry(f, new_journal, o, f->current_offset);
assert_se(r >= 0);
n++;
diff --git a/src/journal/test-journal-init.c b/src/journal/test-journal-init.c
index 074329138b..a43672b6e1 100644
--- a/src/journal/test-journal-init.c
+++ b/src/journal/test-journal-init.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-journal.h"
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
index d87bdbdd32..1f0c9f8f2a 100644
--- a/src/journal/test-journal-interleaving.c
+++ b/src/journal/test-journal-interleaving.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- 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/>.
+ Copyright © 2013 Marius Vollmer
***/
#include <fcntl.h>
@@ -52,7 +36,7 @@ _noreturn_ static void log_assert_errno(const char *text, int error, const char
static JournalFile *test_open(const char *name) {
JournalFile *f;
- assert_ret(journal_file_open(-1, name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, NULL, &f));
+ assert_ret(journal_file_open(-1, name, O_RDWR|O_CREAT, 0644, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &f));
return f;
}
@@ -79,7 +63,7 @@ static void append_number(JournalFile *f, int n, uint64_t *seqnum) {
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));
+ assert_ret(journal_file_append_entry(f, &ts, NULL, iovec, 1, seqnum, NULL, NULL));
free(p);
}
@@ -217,7 +201,7 @@ static void test_sequence_numbers(void) {
assert_se(chdir(t) >= 0);
assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, 0644,
- true, false, NULL, NULL, NULL, NULL, &one) == 0);
+ true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &one) == 0);
append_number(one, 1, &seqnum);
printf("seqnum=%"PRIu64"\n", seqnum);
@@ -234,7 +218,7 @@ static void test_sequence_numbers(void) {
memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t));
assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, 0644,
- true, false, NULL, NULL, NULL, one, &two) == 0);
+ true, (uint64_t) -1, false, NULL, NULL, NULL, one, &two) == 0);
assert_se(two->header->state == STATE_ONLINE);
assert_se(!sd_id128_equal(two->header->file_id, one->header->file_id));
@@ -265,7 +249,7 @@ static void test_sequence_numbers(void) {
seqnum = 0;
assert_se(journal_file_open(-1, "two.journal", O_RDWR, 0,
- true, false, NULL, NULL, NULL, NULL, &two) == 0);
+ true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &two) == 0);
assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id));
diff --git a/src/journal/test-journal-match.c b/src/journal/test-journal-match.c
index 018e965d67..4e5ad1791a 100644
--- a/src/journal/test-journal-match.c
+++ b/src/journal/test-journal-match.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c
index 8e69a52e29..484308e56e 100644
--- a/src/journal/test-journal-send.c
+++ b/src/journal/test-journal-send.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c
index 73ed6e5dcb..ae35c91eff 100644
--- a/src/journal/test-journal-stream.c
+++ b/src/journal/test-journal-stream.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <unistd.h>
@@ -93,9 +75,9 @@ int main(int argc, char *argv[]) {
assert_se(mkdtemp(t));
assert_se(chdir(t) >= 0);
- assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &one) == 0);
- assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &two) == 0);
- assert_se(journal_file_open(-1, "three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &three) == 0);
+ assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &one) == 0);
+ assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &two) == 0);
+ assert_se(journal_file_open(-1, "three.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &three) == 0);
for (i = 0; i < N_ENTRIES; i++) {
char *p, *q;
@@ -122,12 +104,12 @@ int main(int argc, char *argv[]) {
iovec[1].iov_len = strlen(q);
if (i % 10 == 0)
- assert_se(journal_file_append_entry(three, &ts, iovec, 2, NULL, NULL, NULL) == 0);
+ assert_se(journal_file_append_entry(three, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
else {
if (i % 3 == 0)
- assert_se(journal_file_append_entry(two, &ts, iovec, 2, NULL, NULL, NULL) == 0);
+ assert_se(journal_file_append_entry(two, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
- assert_se(journal_file_append_entry(one, &ts, iovec, 2, NULL, NULL, NULL) == 0);
+ assert_se(journal_file_append_entry(one, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
}
free(p);
diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c
index 45ad1196aa..9ba86f6c8a 100644
--- a/src/journal/test-journal-syslog.c
+++ b/src/journal/test-journal-syslog.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "journald-syslog.h"
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index fbb75e43e3..c1c3a82c42 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stdio.h>
@@ -56,7 +38,7 @@ static int raw_verify(const char *fn, const char *verification_key) {
JournalFile *f;
int r;
- r = journal_file_open(-1, fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f);
+ r = journal_file_open(-1, fn, O_RDONLY, 0666, true, (uint64_t) -1, !!verification_key, NULL, NULL, NULL, NULL, &f);
if (r < 0)
return r;
@@ -89,7 +71,7 @@ int main(int argc, char *argv[]) {
log_info("Generating...");
- assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
+ assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
for (n = 0; n < N_ENTRIES; n++) {
struct iovec iovec;
@@ -103,7 +85,7 @@ int main(int argc, char *argv[]) {
iovec.iov_base = (void*) test;
iovec.iov_len = strlen(test);
- assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
+ assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
free(test);
}
@@ -112,7 +94,7 @@ int main(int argc, char *argv[]) {
log_info("Verifying...");
- assert_se(journal_file_open(-1, "test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
+ assert_se(journal_file_open(-1, "test.journal", O_RDONLY, 0666, true, (uint64_t) -1, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0);
/* journal_file_print_header(f); */
journal_file_dump(f);
diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c
index 517c9102a6..69bdff6760 100644
--- a/src/journal/test-journal.c
+++ b/src/journal/test-journal.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <unistd.h>
@@ -36,6 +18,7 @@ static void test_non_empty(void) {
static const char test[] = "TEST1=1", test2[] = "TEST2=2";
Object *o;
uint64_t p;
+ sd_id128_t fake_boot_id;
char t[] = "/tmp/journal-XXXXXX";
log_set_max_level(LOG_DEBUG);
@@ -43,21 +26,22 @@ static void test_non_empty(void) {
assert_se(mkdtemp(t));
assert_se(chdir(t) >= 0);
- assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, NULL, &f) == 0);
+ assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f) == 0);
- dual_timestamp_get(&ts);
+ assert_se(dual_timestamp_get(&ts));
+ assert_se(sd_id128_randomize(&fake_boot_id) == 0);
iovec.iov_base = (void*) test;
iovec.iov_len = strlen(test);
- assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
+ assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
iovec.iov_base = (void*) test2;
iovec.iov_len = strlen(test2);
- assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
+ assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
iovec.iov_base = (void*) test;
iovec.iov_len = strlen(test);
- assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
+ assert_se(journal_file_append_entry(f, &ts, &fake_boot_id, &iovec, 1, NULL, NULL, NULL) == 0);
#if HAVE_GCRYPT
journal_file_append_tag(f);
@@ -72,6 +56,7 @@ static void test_non_empty(void) {
assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 1);
assert_se(le64toh(o->entry.seqnum) == 3);
+ assert_se(sd_id128_equal(o->entry.boot_id, fake_boot_id));
assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 0);
@@ -105,8 +90,8 @@ static void test_non_empty(void) {
assert_se(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0);
- journal_file_rotate(&f, true, true, NULL);
- journal_file_rotate(&f, true, true, NULL);
+ journal_file_rotate(&f, true, (uint64_t) -1, true, NULL);
+ journal_file_rotate(&f, true, (uint64_t) -1, true, NULL);
(void) journal_file_close(f);
@@ -132,13 +117,13 @@ static void test_empty(void) {
assert_se(mkdtemp(t));
assert_se(chdir(t) >= 0);
- assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, false, false, NULL, NULL, NULL, NULL, &f1) == 0);
+ assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, false, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &f1) == 0);
- assert_se(journal_file_open(-1, "test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, NULL, &f2) == 0);
+ assert_se(journal_file_open(-1, "test-compress.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &f2) == 0);
- assert_se(journal_file_open(-1, "test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, NULL, &f3) == 0);
+ assert_se(journal_file_open(-1, "test-seal.journal", O_RDWR|O_CREAT, 0666, false, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f3) == 0);
- assert_se(journal_file_open(-1, "test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, NULL, &f4) == 0);
+ assert_se(journal_file_open(-1, "test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f4) == 0);
journal_file_print_header(f1);
puts("");
@@ -165,6 +150,91 @@ static void test_empty(void) {
(void) journal_file_close(f4);
}
+#if HAVE_XZ || HAVE_LZ4
+static bool check_compressed(uint64_t compress_threshold, uint64_t data_size) {
+ dual_timestamp ts;
+ JournalFile *f;
+ struct iovec iovec;
+ Object *o;
+ uint64_t p;
+ char t[] = "/tmp/journal-XXXXXX";
+ char data[2048] = {0};
+ bool is_compressed;
+ int r;
+
+ assert_se(data_size <= sizeof(data));
+
+ log_set_max_level(LOG_DEBUG);
+
+ assert_se(mkdtemp(t));
+ assert_se(chdir(t) >= 0);
+
+ assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, compress_threshold, true, NULL, NULL, NULL, NULL, &f) == 0);
+
+ dual_timestamp_get(&ts);
+
+ iovec.iov_base = (void*) data;
+ iovec.iov_len = data_size;
+ assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
+
+#if HAVE_GCRYPT
+ journal_file_append_tag(f);
+#endif
+ journal_file_dump(f);
+
+ /* We have to partially reimplement some of the dump logic, because the normal next_entry does the
+ * decompression for us. */
+ p = le64toh(f->header->header_size);
+ for (;;) {
+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
+ assert_se(r == 0);
+ if (o->object.type == OBJECT_DATA)
+ break;
+
+ assert_se(p < le64toh(f->header->tail_object_offset));
+ p = p + ALIGN64(le64toh(o->object.size));
+ }
+
+ is_compressed = (o->object.flags & OBJECT_COMPRESSION_MASK) != 0;
+
+ (void) journal_file_close(f);
+
+ log_info("Done...");
+
+ if (arg_keep)
+ log_info("Not removing %s", t);
+ else {
+ journal_directory_vacuum(".", 3000000, 0, 0, NULL, true);
+
+ assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
+ }
+
+ puts("------------------------------------------------------------");
+
+ return is_compressed;
+}
+
+static void test_min_compress_size(void) {
+ /* Note that XZ will actually fail to compress anything under 80 bytes, so you have to choose the limits
+ * carefully */
+
+ /* DEFAULT_MIN_COMPRESS_SIZE is 512 */
+ assert_se(!check_compressed((uint64_t) -1, 255));
+ assert_se(check_compressed((uint64_t) -1, 513));
+
+ /* compress everything */
+ assert_se(check_compressed(0, 96));
+ assert_se(check_compressed(8, 96));
+
+ /* Ensure we don't try to compress less than 8 bytes */
+ assert_se(!check_compressed(0, 7));
+
+ /* check boundary conditions */
+ assert_se(check_compressed(256, 256));
+ assert_se(!check_compressed(256, 255));
+}
+#endif
+
int main(int argc, char *argv[]) {
arg_keep = argc > 1;
@@ -174,6 +244,9 @@ int main(int argc, char *argv[]) {
test_non_empty();
test_empty();
+#if HAVE_XZ || HAVE_LZ4
+ test_min_compress_size();
+#endif
return 0;
}
diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c
index 39e7510128..5c55b35f57 100644
--- a/src/journal/test-mmap-cache.c
+++ b/src/journal/test-mmap-cache.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stdlib.h>
diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install
index 6eabb09e3c..f9d628a8eb 100644
--- a/src/kernel-install/kernel-install
+++ b/src/kernel-install/kernel-install
@@ -5,7 +5,7 @@
#
# This file is part of systemd.
#
-# Copyright 2013 Harald Hoyer
+# 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
diff --git a/src/kernel-install/meson.build b/src/kernel-install/meson.build
index 65f483f229..c6e6f816d9 100644
--- a/src/kernel-install/meson.build
+++ b/src/kernel-install/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
install_data('kernel-install',
install_mode : 'rwxr-xr-x',
diff --git a/src/libsystemd-network/arp-util.c b/src/libsystemd-network/arp-util.c
index b8e9b2e496..3a86f3f077 100644
--- a/src/libsystemd-network/arp-util.c
+++ b/src/libsystemd-network/arp-util.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
- Copyright (C) 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Axis Communications AB. All rights reserved.
***/
#include <linux/filter.h>
@@ -103,10 +87,7 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
if (r < 0)
return -errno;
- r = s;
- s = -1;
-
- return r;
+ return TAKE_FD(s);
}
static int arp_send_packet(int fd, int ifindex,
diff --git a/src/libsystemd-network/arp-util.h b/src/libsystemd-network/arp-util.h
index decfce3fd6..10c684864b 100644
--- a/src/libsystemd-network/arp-util.h
+++ b/src/libsystemd-network/arp-util.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Axis Communications AB. All rights reserved.
***/
#include <netinet/if_ether.h>
diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c
index f33817ca7d..91c485c6c2 100644
--- a/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libsystemd-network/dhcp-identifier.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2015 Tom Gundersen <teg@jklmen>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "sd-id128.h"
@@ -91,13 +73,13 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
/* name is a pointer to memory in the udev_device struct, so must
have the same scope */
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
const char *name = NULL;
uint64_t id;
if (detect_container() <= 0) {
/* not in a container, udev will be around */
- _cleanup_udev_unref_ struct udev *udev;
+ _cleanup_(udev_unrefp) struct udev *udev;
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
udev = udev_new();
diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h
index 0ccee7a718..b92c580d40 100644
--- a/src/libsystemd-network/dhcp-identifier.h
+++ b/src/libsystemd-network/dhcp-identifier.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright (C) 2015 Tom Gundersen <teg@jklmen>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-id128.h"
diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index a53526956a..a0f9c2299f 100644
--- a/src/libsystemd-network/dhcp-internal.h
+++ b/src/libsystemd-network/dhcp-internal.h
@@ -2,23 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <linux/if_packet.h>
diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h
index 65c182f48b..9d245a9059 100644
--- a/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/libsystemd-network/dhcp-lease-internal.h
@@ -2,23 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <stdint.h>
diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c
index 602bf08a60..77638338f2 100644
--- a/src/libsystemd-network/dhcp-network.c
+++ b/src/libsystemd-network/dhcp-network.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -123,10 +108,7 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
if (r < 0)
return -errno;
- r = s;
- s = -1;
-
- return r;
+ return TAKE_FD(s);
}
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
@@ -211,10 +193,7 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
if (r < 0)
return -errno;
- r = s;
- s = -1;
-
- return r;
+ return TAKE_FD(s);
}
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 0489579e7f..ad3f92546d 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -25,6 +10,7 @@
#include "alloc-util.h"
#include "utf8.h"
+#include "strv.h"
#include "dhcp-internal.h"
@@ -48,6 +34,34 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
*offset += 1;
break;
+ case SD_DHCP_OPTION_USER_CLASS: {
+ size_t len = 0;
+ char **s;
+
+ STRV_FOREACH(s, (char **) optval)
+ len += strlen(*s) + 1;
+
+ if (size < *offset + len + 2)
+ return -ENOBUFS;
+
+ options[*offset] = code;
+ options[*offset + 1] = len;
+ *offset += 2;
+
+ STRV_FOREACH(s, (char **) optval) {
+ len = strlen(*s);
+
+ if (len > 255)
+ return -ENAMETOOLONG;
+
+ options[*offset] = len;
+
+ memcpy_safe(&options[*offset + 1], *s, len);
+ *offset += len + 1;
+ }
+
+ break;
+ }
default:
if (size < *offset + optlen + 2)
return -ENOBUFS;
@@ -253,10 +267,8 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t c
if (message_type == 0)
return -ENOMSG;
- if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE)) {
- *_error_message = error_message;
- error_message = NULL;
- }
+ if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE))
+ *_error_message = TAKE_PTR(error_message);
return message_type;
}
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index 1c4ab5d52f..d29cd06cb1 100644
--- a/src/libsystemd-network/dhcp-packet.c
+++ b/src/libsystemd-network/dhcp-packet.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <errno.h>
diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h
index 73a9f75e75..f03663248a 100644
--- a/src/libsystemd-network/dhcp-protocol.h
+++ b/src/libsystemd-network/dhcp-protocol.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <netinet/ip.h>
diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h
index 8b5620e138..6355128ddb 100644
--- a/src/libsystemd-network/dhcp-server-internal.h
+++ b/src/libsystemd-network/dhcp-server-internal.h
@@ -2,23 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include "sd-dhcp-server.h"
@@ -86,6 +70,7 @@ typedef struct DHCPRequest {
} DHCPRequest;
#define log_dhcp_server(client, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__)
+#define log_dhcp_server_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__)
int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
size_t length);
diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h
index 13844a86c6..f1cbd6a4f1 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include <net/ethernet.h>
diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h
index 45e0e82427..ff0b0f00ce 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -2,23 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include <stdint.h>
diff --git a/src/libsystemd-network/dhcp6-network.c b/src/libsystemd-network/dhcp6-network.c
index b3b8fddbcb..78cd383669 100644
--- a/src/libsystemd-network/dhcp6-network.c
+++ b/src/libsystemd-network/dhcp6-network.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -67,9 +52,7 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
if (r < 0)
return -errno;
- r = s;
- s = -1;
- return r;
+ return TAKE_FD(s);
}
int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c
index df96ad739d..18196b1257 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -154,7 +139,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
}
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
- uint8_t buffer[1 + DNS_WIRE_FOMAT_HOSTNAME_MAX];
+ uint8_t buffer[1 + DNS_WIRE_FORMAT_HOSTNAME_MAX];
int r;
assert_return(buf && *buf && buflen && fqdn, -EINVAL);
@@ -617,8 +602,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
idx++;
}
- *str_arr = names;
- names = NULL;
+ *str_arr = TAKE_PTR(names);
return idx;
diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h
index 5f7e809ba1..ffae4453ac 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <netinet/ip6.h>
diff --git a/src/libsystemd-network/icmp6-util.c b/src/libsystemd-network/icmp6-util.c
index dd4e28bfd9..736df222f0 100644
--- a/src/libsystemd-network/icmp6-util.c
+++ b/src/libsystemd-network/icmp6-util.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -98,9 +83,7 @@ static int icmp6_bind_router_message(const struct icmp6_filter *filter,
if (r < 0)
return -errno;
- r = s;
- s = -1;
- return r;
+ return TAKE_FD(s);
}
int icmp6_bind_router_solicitation(int index) {
diff --git a/src/libsystemd-network/icmp6-util.h b/src/libsystemd-network/icmp6-util.h
index ce14f41736..725a68086b 100644
--- a/src/libsystemd-network/icmp6-util.h
+++ b/src/libsystemd-network/icmp6-util.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include <net/ethernet.h>
diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h
index 2673aa1c55..7c10a67a35 100644
--- a/src/libsystemd-network/lldp-internal.h
+++ b/src/libsystemd-network/lldp-internal.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-event.h"
#include "sd-lldp.h"
diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c
index 1a6ea288aa..5dcb051373 100644
--- a/src/libsystemd-network/lldp-neighbor.c
+++ b/src/libsystemd-network/lldp-neighbor.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "escape.h"
@@ -341,7 +323,6 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
break;
}
-
p += length, left -= length;
}
@@ -674,8 +655,7 @@ _public_ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw,
if (r < 0)
return r;
- *ret = n;
- n = NULL;
+ *ret = TAKE_PTR(n);
return r;
}
diff --git a/src/libsystemd-network/lldp-neighbor.h b/src/libsystemd-network/lldp-neighbor.h
index 76d4c0c724..494bc51760 100644
--- a/src/libsystemd-network/lldp-neighbor.h
+++ b/src/libsystemd-network/lldp-neighbor.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/libsystemd-network/lldp-network.c b/src/libsystemd-network/lldp-network.c
index cb3841ef22..a4020d1e19 100644
--- a/src/libsystemd-network/lldp-network.c
+++ b/src/libsystemd-network/lldp-network.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/filter.h>
#include <netinet/if_ether.h>
@@ -92,8 +73,5 @@ int lldp_network_bind_raw_socket(int ifindex) {
if (r < 0)
return -errno;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
diff --git a/src/libsystemd-network/lldp-network.h b/src/libsystemd-network/lldp-network.h
index c0f8cbe1c9..914139793c 100644
--- a/src/libsystemd-network/lldp-network.h
+++ b/src/libsystemd-network/lldp-network.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-event.h"
diff --git a/src/libsystemd-network/meson.build b/src/libsystemd-network/meson.build
index c710ab44a9..56d470ff68 100644
--- a/src/libsystemd-network/meson.build
+++ b/src/libsystemd-network/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
sources = files('''
sd-dhcp-client.c
diff --git a/src/libsystemd-network/ndisc-internal.h b/src/libsystemd-network/ndisc-internal.h
index 2743d85efc..fdabbc1b0e 100644
--- a/src/libsystemd-network/ndisc-internal.h
+++ b/src/libsystemd-network/ndisc-internal.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include "log.h"
diff --git a/src/libsystemd-network/ndisc-router.c b/src/libsystemd-network/ndisc-router.c
index 2954928d00..25b693a458 100644
--- a/src/libsystemd-network/ndisc-router.c
+++ b/src/libsystemd-network/ndisc-router.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <netinet/icmp6.h>
@@ -82,8 +67,7 @@ _public_ int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, si
if (r < 0)
return r;
- *ret = rt;
- rt = NULL;
+ *ret = TAKE_PTR(rt);
return r;
}
@@ -765,8 +749,7 @@ _public_ int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret)
return 0;
}
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
return k;
}
diff --git a/src/libsystemd-network/ndisc-router.h b/src/libsystemd-network/ndisc-router.h
index f3757f6dbb..2e2c1afd12 100644
--- a/src/libsystemd-network/ndisc-router.h
+++ b/src/libsystemd-network/ndisc-router.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include "sd-ndisc.h"
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 584a1f36ac..0849b44ee2 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <linux/if.h>
@@ -96,7 +78,7 @@ static bool net_condition_test_strv(char * const *raw_patterns,
/* If the patterns begin with "!", edit it out and negate the test. */
if (raw_patterns[0][0] == '!') {
char **patterns;
- unsigned i, length;
+ size_t i, length;
length = strv_length(raw_patterns) + 1; /* Include the NULL. */
patterns = newa(char*, length);
@@ -110,7 +92,7 @@ static bool net_condition_test_strv(char * const *raw_patterns,
return string && strv_fnmatch(raw_patterns, string, 0);
}
-bool net_match_config(const struct ether_addr *match_mac,
+bool net_match_config(Set *match_mac,
char * const *match_paths,
char * const *match_drivers,
char * const *match_types,
@@ -142,7 +124,7 @@ bool net_match_config(const struct ether_addr *match_mac,
if (match_arch && condition_test(match_arch) <= 0)
return false;
- if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
+ if (match_mac && dev_mac && !set_contains(match_mac, dev_mac))
return false;
if (!net_condition_test_strv(match_paths, dev_path))
@@ -276,10 +258,9 @@ int config_parse_ifalias(const char *unit,
}
free(*s);
- if (*n) {
- *s = n;
- n = NULL;
- } else
+ if (*n)
+ *s = TAKE_PTR(n);
+ else
*s = NULL;
return 0;
@@ -295,10 +276,9 @@ int config_parse_hwaddr(const char *unit,
const char *rvalue,
void *data,
void *userdata) {
+
+ _cleanup_free_ struct ether_addr *n = NULL;
struct ether_addr **hwaddr = data;
- struct ether_addr *n;
- const char *start;
- size_t offset;
int r;
assert(filename);
@@ -310,17 +290,86 @@ int config_parse_hwaddr(const char *unit,
if (!n)
return log_oom();
- start = rvalue + strspn(rvalue, WHITESPACE);
- r = ether_addr_from_string(start, n, &offset);
+ r = ether_addr_from_string(rvalue, n);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ *hwaddr = TAKE_PTR(n);
+
+ return 0;
+}
+
+int config_parse_hwaddrs(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_set_free_free_ Set *s = NULL;
+ const char *p = rvalue;
+ Set **hwaddrs = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
- if (r || (start[offset + strspn(start + offset, WHITESPACE)] != '\0')) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
- free(n);
+ if (isempty(rvalue)) {
+ /* Empty assignment resets the list */
+ *hwaddrs = set_free_free(*hwaddrs);
return 0;
}
- free(*hwaddr);
- *hwaddr = n;
+ s = set_new(&ether_addr_hash_ops);
+ if (!s)
+ return log_oom();
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ _cleanup_free_ struct ether_addr *n = NULL;
+
+ r = extract_first_word(&p, &word, NULL, 0);
+ if (r == 0)
+ break;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ n = new(struct ether_addr, 1);
+ if (!n)
+ return log_oom();
+
+ r = ether_addr_from_string(word, n);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring: %s", word);
+ continue;
+ }
+
+ r = set_put(s, n);
+ if (r < 0)
+ return log_oom();
+ if (r > 0)
+ n = NULL; /* avoid cleanup */
+ }
+
+ r = set_ensure_allocated(hwaddrs, &ether_addr_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ r = set_move(*hwaddrs, s);
+ if (r < 0)
+ return log_oom();
return 0;
}
@@ -393,7 +442,6 @@ int config_parse_bridge_port_priority(
return 0;
}
-
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
unsigned i;
@@ -437,8 +485,7 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
size++;
}
- *ret = addresses;
- addresses = NULL;
+ *ret = TAKE_PTR(addresses);
return size;
}
@@ -491,8 +538,7 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
size++;
}
- *ret = addresses;
- addresses = NULL;
+ *ret = TAKE_PTR(addresses);
return size;
}
@@ -585,8 +631,7 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t
*ret_size = size;
*ret_allocated = allocated;
- *ret = routes;
- routes = NULL;
+ *ret = TAKE_PTR(routes);
return 0;
}
@@ -606,14 +651,3 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz
return 0;
}
-
-int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
- assert(data);
- assert(data_len);
- assert(string);
-
- if (strlen(string) % 2)
- return -EINVAL;
-
- return unhexmem(string, strlen(string), (void **)data, data_len);
-}
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index 4e69f1a598..883f34b95c 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -1,36 +1,20 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
#include "sd-dhcp-lease.h"
#include "condition.h"
+#include "conf-parser.h"
+#include "set.h"
#include "udev.h"
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
-bool net_match_config(const struct ether_addr *match_mac,
+bool net_match_config(Set *match_mac,
char * const *match_path,
char * const *match_driver,
char * const *match_type,
@@ -47,29 +31,13 @@ bool net_match_config(const struct ether_addr *match_mac,
const char *dev_type,
const char *dev_name);
-int config_parse_net_condition(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_hwaddr(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_ifnames(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_ifalias(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_iaid(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_bridge_port_priority(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
+CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
+CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
+CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
+CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
const char *net_get_name(struct udev_device *device);
@@ -86,5 +54,5 @@ struct sd_dhcp_route;
void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size);
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
+/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
-int deserialize_dhcp_option(void **data, size_t *data_len, const char *string);
diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h
index 837e7f2603..b221c6f6c5 100644
--- a/src/libsystemd-network/radv-internal.h
+++ b/src/libsystemd-network/radv-internal.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2017 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2017 Intel Corporation. All rights reserved.
***/
#include "sd-radv.h"
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 33f3469f07..ff434f8ce7 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -40,6 +25,7 @@
#include "random-util.h"
#include "string-util.h"
#include "util.h"
+#include "strv.h"
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
@@ -96,6 +82,7 @@ struct sd_dhcp_client {
size_t client_id_len;
char *hostname;
char *vendor_class_identifier;
+ char **user_class;
uint32_t mtu;
uint32_t xid;
usec_t start_time;
@@ -354,9 +341,10 @@ int sd_dhcp_client_set_client_id(
* without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned.
*/
-int sd_dhcp_client_set_iaid_duid(
+static int dhcp_client_set_iaid_duid(
sd_dhcp_client *client,
uint32_t iaid,
+ bool append_iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len) {
@@ -377,15 +365,17 @@ int sd_dhcp_client_set_iaid_duid(
zero(client->client_id);
client->client_id.type = 255;
- /* If IAID is not configured, generate it. */
- if (iaid == 0) {
- r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
- client->mac_addr_len,
- &client->client_id.ns.iaid);
- if (r < 0)
- return r;
- } else
- client->client_id.ns.iaid = htobe32(iaid);
+ if (append_iaid) {
+ /* If IAID is not configured, generate it. */
+ if (iaid == 0) {
+ r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
+ client->mac_addr_len,
+ &client->client_id.ns.iaid);
+ if (r < 0)
+ return r;
+ } else
+ client->client_id.ns.iaid = htobe32(iaid);
+ }
if (duid != NULL) {
client->client_id.ns.duid.type = htobe16(duid_type);
@@ -399,7 +389,7 @@ int sd_dhcp_client_set_iaid_duid(
return -EOPNOTSUPP;
client->client_id_len = sizeof(client->client_id.type) + len +
- sizeof(client->client_id.ns.iaid);
+ (append_iaid ? sizeof(client->client_id.ns.iaid) : 0);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Configured IAID+DUID, restarting.");
@@ -410,6 +400,23 @@ int sd_dhcp_client_set_iaid_duid(
return 0;
}
+int sd_dhcp_client_set_iaid_duid(
+ sd_dhcp_client *client,
+ uint32_t iaid,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len) {
+ return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len);
+}
+
+int sd_dhcp_client_set_duid(
+ sd_dhcp_client *client,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len) {
+ return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len);
+}
+
int sd_dhcp_client_set_hostname(
sd_dhcp_client *client,
const char *hostname) {
@@ -433,6 +440,26 @@ int sd_dhcp_client_set_vendor_class_identifier(
return free_and_strdup(&client->vendor_class_identifier, vci);
}
+int sd_dhcp_client_set_user_class(
+ sd_dhcp_client *client,
+ const char* const* user_class) {
+
+ _cleanup_strv_free_ char **s = NULL;
+ char **p;
+
+ STRV_FOREACH(p, (char **) user_class)
+ if (strlen(*p) > 255)
+ return -ENAMETOOLONG;
+
+ s = strv_copy((char **) user_class);
+ if (!s)
+ return -ENOMEM;
+
+ client->user_class = TAKE_PTR(s);
+
+ return 0;
+}
+
int sd_dhcp_client_set_client_port(
sd_dhcp_client *client,
uint16_t port) {
@@ -662,8 +689,7 @@ static int client_message_init(
*_optlen = optlen;
*_optoffset = optoffset;
- *ret = packet;
- packet = NULL;
+ *ret = TAKE_PTR(packet);
return 0;
}
@@ -757,6 +783,15 @@ static int client_send_discover(sd_dhcp_client *client) {
return r;
}
+ if (client->user_class) {
+ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_USER_CLASS,
+ strv_length(client->user_class),
+ client->user_class);
+ if (r < 0)
+ return r;
+ }
+
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
@@ -1268,8 +1303,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_
}
sd_dhcp_lease_unref(client->lease);
- client->lease = lease;
- lease = NULL;
+ client->lease = TAKE_PTR(lease);
log_dhcp_client(client, "OFFER");
@@ -1350,8 +1384,7 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t le
client->lease = sd_dhcp_lease_unref(client->lease);
}
- client->lease = lease;
- lease = NULL;
+ client->lease = TAKE_PTR(lease);
log_dhcp_client(client, "ACK");
@@ -1914,6 +1947,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);
+ client->user_class = strv_free(client->user_class);
return mfree(client);
}
@@ -1946,8 +1980,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
if (!client->req_opts)
return -ENOMEM;
- *ret = client;
- client = NULL;
+ *ret = TAKE_PTR(client);
return 0;
}
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 2e88e39878..dbd80442e6 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <arpa/inet.h>
@@ -234,7 +218,7 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
}
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
- unsigned r;
+ size_t r;
assert_return(lease, -EINVAL);
assert_return(domains, -EINVAL);
@@ -680,7 +664,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
return 0;
}
- if (!timezone_is_valid(tz)) {
+ if (!timezone_is_valid(tz, LOG_DEBUG)) {
log_debug_errno(r, "Timezone is not valid, ignoring: %m");
return 0;
}
@@ -807,8 +791,7 @@ int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***d
pos = next_chunk;
}
- *domains = names;
- names = NULL;
+ *domains = TAKE_PTR(names);
return cnt;
}
@@ -1048,7 +1031,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
if (r < 0)
return r;
- r = parse_env_file(lease_file, NEWLINE,
+ r = parse_env_file(NULL, lease_file, NEWLINE,
"ADDRESS", &address,
"ROUTER", &router,
"NETMASK", &netmask,
@@ -1207,13 +1190,13 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
}
if (client_id_hex) {
- r = deserialize_dhcp_option(&lease->client_id, &lease->client_id_len, client_id_hex);
+ r = unhexmem(client_id_hex, (size_t) -1, &lease->client_id, &lease->client_id_len);
if (r < 0)
log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex);
}
if (vendor_specific_hex) {
- r = deserialize_dhcp_option(&lease->vendor_specific, &lease->vendor_specific_len, vendor_specific_hex);
+ r = unhexmem(vendor_specific_hex, (size_t) -1, &lease->vendor_specific, &lease->vendor_specific_len);
if (r < 0)
log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
}
@@ -1225,7 +1208,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
if (!options[i])
continue;
- r = deserialize_dhcp_option(&data, &len, options[i]);
+ r = unhexmem(options[i], (size_t) -1, &data, &len);
if (r < 0) {
log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]);
continue;
@@ -1236,8 +1219,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
return r;
}
- *ret = lease;
- lease = NULL;
+ *ret = TAKE_PTR(lease);
return 0;
}
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index d64a47d2fc..5ca46b3502 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <sys/ioctl.h>
@@ -213,8 +197,7 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC);
server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC);
- *ret = server;
- server = NULL;
+ *ret = TAKE_PTR(server);
return 0;
}
@@ -313,7 +296,6 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
};
struct cmsghdr *cmsg;
struct in_pktinfo *pktinfo;
- int r;
assert(server);
assert(server->fd >= 0);
@@ -337,8 +319,7 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
pktinfo->ipi_ifindex = server->ifindex;
pktinfo->ipi_spec_dst.s_addr = server->address;
- r = sendmsg(server->fd, &msg, 0);
- if (r < 0)
+ if (sendmsg(server->fd, &msg, 0) < 0)
return -errno;
return 0;
@@ -448,8 +429,7 @@ static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN);
*_optoffset = optoffset;
- *ret = packet;
- packet = NULL;
+ *ret = TAKE_PTR(packet);
return 0;
}
@@ -662,7 +642,6 @@ static void dhcp_request_free(DHCPRequest *req) {
}
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);
-#define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) {
assert(req);
@@ -715,7 +694,7 @@ static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) {
int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
size_t length) {
- _cleanup_dhcp_request_free_ DHCPRequest *req = NULL;
+ _cleanup_(dhcp_request_freep) DHCPRequest *req = NULL;
_cleanup_free_ char *error_message = NULL;
DHCPLease *existing_lease;
int type, r;
@@ -778,8 +757,9 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
if (!server->bound_leases[next_offer]) {
address = server->subnet | htobe32(server->pool_offset + next_offer);
break;
- } else
- next_offer = (next_offer + 1) % server->pool_size;
+ }
+
+ next_offer = (next_offer + 1) % server->pool_size;
}
}
@@ -788,18 +768,12 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
return 0;
r = server_send_offer(server, req, address);
- if (r < 0) {
+ if (r < 0)
/* this only fails on critical errors */
- log_dhcp_server(server, "could not send offer: %s",
- strerror(-r));
- return r;
- } else {
- log_dhcp_server(server, "OFFER (0x%x)",
- be32toh(req->message->xid));
- return DHCP_OFFER;
- }
+ return log_dhcp_server_errno(server, r, "Could not send offer: %m");
- break;
+ log_dhcp_server(server, "OFFER (0x%x)", be32toh(req->message->xid));
+ return DHCP_OFFER;
}
case DHCP_DECLINE:
log_dhcp_server(server, "DECLINE (0x%x): %s", be32toh(req->message->xid), strna(error_message));
@@ -899,8 +873,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
r = server_send_ack(server, req, address);
if (r < 0) {
/* this only fails on critical errors */
- log_dhcp_server(server, "could not send ack: %s",
- strerror(-r));
+ log_dhcp_server_errno(server, r, "Could not send ack: %m");
if (!existing_lease)
dhcp_lease_free(lease);
@@ -916,18 +889,15 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
return DHCP_ACK;
}
+
} else if (init_reboot) {
r = server_send_nak(server, req);
- if (r < 0) {
+ if (r < 0)
/* this only fails on critical errors */
- log_dhcp_server(server, "could not send nak: %s",
- strerror(-r));
- return r;
- } else {
- log_dhcp_server(server, "NAK (0x%x)",
- be32toh(req->message->xid));
- return DHCP_NAK;
- }
+ return log_dhcp_server_errno(server, r, "Could not send nak: %m");
+
+ log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid));
+ return DHCP_NAK;
}
break;
@@ -953,12 +923,10 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
server->bound_leases[pool_offset] = NULL;
hashmap_remove(server->leases_by_client_id, existing_lease);
dhcp_lease_free(existing_lease);
+ }
- return 1;
- } else
- return 0;
- }
- }
+ return 0;
+ }}
return 0;
}
@@ -977,6 +945,7 @@ static int server_receive_message(sd_event_source *s, int fd,
};
struct cmsghdr *cmsg;
ssize_t buflen, len;
+ int r;
assert(server);
@@ -997,7 +966,8 @@ static int server_receive_message(sd_event_source *s, int fd,
return 0;
return -errno;
- } else if ((size_t)len < sizeof(DHCPMessage))
+ }
+ if ((size_t)len < sizeof(DHCPMessage))
return 0;
CMSG_FOREACH(cmsg, &msg) {
@@ -1015,7 +985,11 @@ static int server_receive_message(sd_event_source *s, int fd,
}
}
- return dhcp_server_handle_message(server, message, (size_t)len);
+ r = dhcp_server_handle_message(server, message, (size_t) len);
+ if (r < 0)
+ log_dhcp_server_errno(server, r, "Couldn't process incoming message: %m");
+
+ return 0;
}
int sd_dhcp_server_start(sd_dhcp_server *server) {
@@ -1024,8 +998,8 @@ int sd_dhcp_server_start(sd_dhcp_server *server) {
assert_return(server, -EINVAL);
assert_return(server->event, -EINVAL);
assert_return(!server->receive_message, -EBUSY);
- assert_return(server->fd_raw == -1, -EBUSY);
- assert_return(server->fd == -1, -EBUSY);
+ assert_return(server->fd_raw < 0, -EBUSY);
+ assert_return(server->fd < 0, -EBUSY);
assert_return(server->address != htobe32(INADDR_ANY), -EUNATCH);
r = socket(AF_PACKET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
@@ -1081,8 +1055,8 @@ int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
lease->chaddr);
if (r < 0)
return r;
- else
- log_dhcp_server(server, "FORCERENEW");
+
+ log_dhcp_server(server, "FORCERENEW");
}
return r;
@@ -1092,7 +1066,7 @@ int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) {
int r;
assert_return(server, -EINVAL);
- assert_return(timezone_is_valid(tz), -EINVAL);
+ assert_return(timezone_is_valid(tz, LOG_DEBUG), -EINVAL);
if (streq_ptr(tz, server->timezone))
return 0;
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 056bfa3d3d..b3bc259280 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -1466,8 +1451,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
for (t = 0; t < client->req_opts_len; t++)
client->req_opts[t] = htobe16(default_req_opts[t]);
- *ret = client;
- client = NULL;
+ *ret = TAKE_PTR(client);
return 0;
}
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c
index 0089fbb737..779ad54b4a 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -261,8 +245,7 @@ int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
if (r < 0)
return 0;
- strv_free(lease->domains);
- lease->domains = domains;
+ strv_free_and_replace(lease->domains, domains);
lease->domains_count = r;
return r;
@@ -321,8 +304,7 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
if (r < 0)
return 0;
- lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
- lease->ntp_fqdn = servers;
+ strv_free_and_replace(lease->ntp_fqdn, servers);
lease->ntp_fqdn_count = r;
break;
diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c
index 7cf4f031de..a40d40db90 100644
--- a/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/libsystemd-network/sd-ipv4acd.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
- Copyright (C) 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Axis Communications AB. All rights reserved.
***/
#include <arpa/inet.h>
@@ -153,8 +137,7 @@ int sd_ipv4acd_new(sd_ipv4acd **ret) {
acd->ifindex = -1;
acd->fd = -1;
- *ret = acd;
- acd = NULL;
+ *ret = TAKE_PTR(acd);
return 0;
}
@@ -207,8 +190,7 @@ static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_u
(void) sd_event_source_set_description(timer, "ipv4acd-timer");
sd_event_source_unref(acd->timer_event_source);
- acd->timer_event_source = timer;
- timer = NULL;
+ acd->timer_event_source = TAKE_PTR(timer);
return 0;
}
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index f3d09eb30a..7307e1668f 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
- Copyright (C) 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Axis Communications AB. All rights reserved.
***/
#include <arpa/inet.h>
@@ -115,8 +99,7 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) {
if (r < 0)
return r;
- *ret = ll;
- ll = NULL;
+ *ret = TAKE_PTR(ll);
return 0;
}
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index 2c05416184..c75d6079e1 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <linux/sockios.h>
@@ -402,8 +383,7 @@ _public_ int sd_lldp_new(sd_lldp **ret) {
if (r < 0)
return r;
- *ret = lldp;
- lldp = NULL;
+ *ret = TAKE_PTR(lldp);
return 0;
}
@@ -416,15 +396,15 @@ static int neighbor_compare_func(const void *a, const void *b) {
static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
sd_lldp *lldp = userdata;
- int r, q;
+ int r;
r = lldp_make_space(lldp, 0);
if (r < 0)
return log_lldp_errno(r, "Failed to make space: %m");
- q = lldp_start_timer(lldp, NULL);
- if (q < 0)
- return log_lldp_errno(q, "Failed to restart timer: %m");
+ r = lldp_start_timer(lldp, NULL);
+ if (r < 0)
+ return log_lldp_errno(r, "Failed to restart timer: %m");
return 0;
}
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index b5c6d6e84d..2d81160b02 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <netinet/icmp6.h>
@@ -166,8 +151,7 @@ _public_ int sd_ndisc_new(sd_ndisc **ret) {
nd->n_ref = 1;
nd->fd = -1;
- *ret = nd;
- nd = NULL;
+ *ret = TAKE_PTR(nd);
return 0;
}
diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c
index f30d6164ea..86750b876c 100644
--- a/src/libsystemd-network/sd-radv.c
+++ b/src/libsystemd-network/sd-radv.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2017 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2017 Intel Corporation. All rights reserved.
***/
#include <netinet/icmp6.h>
@@ -51,8 +36,7 @@ _public_ int sd_radv_new(sd_radv **ret) {
LIST_HEAD_INIT(ra->prefixes);
- *ret = ra;
- ra = NULL;
+ *ret = TAKE_PTR(ra);
return 0;
}
@@ -91,6 +75,7 @@ _public_ sd_event *sd_radv_get_event(sd_radv *ra) {
}
static void radv_reset(sd_radv *ra) {
+ assert(ra);
ra->timeout_event_source =
sd_event_source_unref(ra->timeout_event_source);
@@ -134,6 +119,9 @@ _public_ sd_radv *sd_radv_unref(sd_radv *ra) {
radv_reset(ra);
sd_radv_detach_event(ra);
+
+ ra->fd = safe_close(ra->fd);
+
return mfree(ra);
}
@@ -288,7 +276,7 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
r = radv_send(ra, &src, ra->lifetime);
if (r < 0)
- log_radv_warning_errno(r, "Unable to send solicited Router Advertisment to %s: %m", addr);
+ log_radv_warning_errno(r, "Unable to send solicited Router Advertisement to %s: %m", addr);
else
log_radv("Sent solicited Router Advertisement to %s", addr);
@@ -366,6 +354,9 @@ _public_ int sd_radv_stop(sd_radv *ra) {
assert_return(ra, -EINVAL);
+ if (ra->state == SD_RADV_STATE_IDLE)
+ return 0;
+
log_radv("Stopping IPv6 Router Advertisement daemon");
/* RFC 4861, Section 6.2.5, send at least one Router Advertisement
@@ -618,8 +609,8 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, bool dynamic) {
}
_public_ sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra,
- struct in6_addr *prefix,
- uint8_t prefixlen) {
+ const struct in6_addr *prefix,
+ unsigned char prefixlen) {
sd_radv_prefix *cur, *next;
assert_return(ra, NULL);
@@ -670,9 +661,7 @@ _public_ int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime,
memcpy(opt_rdnss + 1, dns, n_dns * sizeof(struct in6_addr));
- free(ra->rdnss);
- ra->rdnss = opt_rdnss;
- opt_rdnss = NULL;
+ free_and_replace(ra->rdnss, opt_rdnss);
ra->n_rdnss = n_dns;
@@ -688,9 +677,8 @@ _public_ int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime,
assert_return(ra, -EINVAL);
- if (!search_list || *search_list == NULL) {
+ if (strv_isempty(search_list)) {
ra->dnssl = mfree(ra->dnssl);
-
return 0;
}
@@ -724,9 +712,7 @@ _public_ int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime,
len -= r;
}
- free(ra->dnssl);
- ra->dnssl = opt_dnssl;
- opt_dnssl = NULL;
+ free_and_replace(ra->dnssl, opt_dnssl);
return 0;
}
@@ -755,8 +741,7 @@ _public_ int sd_radv_prefix_new(sd_radv_prefix **ret) {
LIST_INIT(prefix, p);
- *ret = p;
- p = NULL;
+ *ret = TAKE_PTR(p);
return 0;
}
@@ -784,7 +769,7 @@ _public_ sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *p) {
return mfree(p);
}
-_public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, struct in6_addr *in6_addr,
+_public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, const struct in6_addr *in6_addr,
unsigned char prefixlen) {
assert_return(p, -EINVAL);
assert_return(in6_addr, -EINVAL);
diff --git a/src/libsystemd-network/test-acd.c b/src/libsystemd-network/test-acd.c
index 7968c9056a..079e760996 100644
--- a/src/libsystemd-network/test-acd.c
+++ b/src/libsystemd-network/test-acd.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 0e25310e59..0e257633b8 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <errno.h>
@@ -552,7 +537,7 @@ int main(int argc, char *argv[]) {
test_discover_message(e);
test_addr_acq(e);
-#ifdef VALGRIND
+#if VALGRIND
/* Make sure the async_close thread has finished.
* valgrind would report some of the phread_* structures
* as not cleaned up properly. */
diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c
index 6632316b1e..815b11e997 100644
--- a/src/libsystemd-network/test-dhcp-server.c
+++ b/src/libsystemd-network/test-dhcp-server.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <errno.h>
diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c
index aae49fa467..27c0002fe2 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <net/ethernet.h>
@@ -584,7 +569,6 @@ static int test_client_verify_request(DHCP6Message *request, size_t len) {
assert_se(!found_iana);
found_iana = true;
-
assert_se(optlen == 40);
assert_se(!memcmp(optval, &test_iaid, sizeof(test_iaid)));
diff --git a/src/libsystemd-network/test-ipv4ll-manual.c b/src/libsystemd-network/test-ipv4ll-manual.c
index 37092ea300..125133f039 100644
--- a/src/libsystemd-network/test-ipv4ll-manual.c
+++ b/src/libsystemd-network/test-ipv4ll-manual.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <net/if.h>
diff --git a/src/libsystemd-network/test-ipv4ll.c b/src/libsystemd-network/test-ipv4ll.c
index d0620596e5..ee9cce02a8 100644
--- a/src/libsystemd-network/test-ipv4ll.c
+++ b/src/libsystemd-network/test-ipv4ll.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Axis Communications AB. All rights reserved.
***/
#include <errno.h>
diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c
index 5f6829cf6d..ac8ba2b707 100644
--- a/src/libsystemd-network/test-lldp.c
+++ b/src/libsystemd-network/test-lldp.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <errno.h>
diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c
index 1fc8ca9eba..d5a0237663 100644
--- a/src/libsystemd-network/test-ndisc-ra.c
+++ b/src/libsystemd-network/test-ndisc-ra.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2017 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2017 Intel Corporation. All rights reserved.
***/
#include <netinet/icmp6.h>
diff --git a/src/libsystemd-network/test-ndisc-rs.c b/src/libsystemd-network/test-ndisc-rs.c
index e1a2b9f7a2..b9d0e7dc90 100644
--- a/src/libsystemd-network/test-ndisc-rs.c
+++ b/src/libsystemd-network/test-ndisc-rs.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <netinet/icmp6.h>
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 7ff5816180..1eec17db50 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -1,8 +1,6 @@
/***
SPDX-License-Identifier: LGPL-2.1+
- 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
@@ -555,3 +553,20 @@ global:
sd_bus_get_n_queued_read;
sd_bus_get_n_queued_write;
} LIBSYSTEMD_237;
+
+LIBSYSTEMD_239 {
+global:
+ sd_bus_open_with_description;
+ sd_bus_open_user_with_description;
+ sd_bus_open_system_with_description;
+ sd_bus_slot_get_floating;
+ sd_bus_slot_set_floating;
+ sd_bus_slot_get_destroy_callback;
+ sd_bus_slot_set_destroy_callback;
+ sd_bus_track_get_destroy_callback;
+ sd_bus_track_set_destroy_callback;
+ sd_event_add_inotify;
+ sd_event_source_get_inotify_mask;
+ sd_event_source_set_destroy_callback;
+ sd_event_source_get_destroy_callback;
+} LIBSYSTEMD_238;
diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build
index bd72e3d691..070fd6c633 100644
--- a/src/libsystemd/meson.build
+++ b/src/libsystemd/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
id128_sources = files('''
sd-id128/id128-util.c
@@ -95,15 +80,17 @@ libsystemd_sources = files('''
sd-utf8/sd-utf8.c
'''.split()) + id128_sources + sd_daemon_c + sd_event_c + sd_login_c
+libsystemd_c_args = ['-fvisibility=default']
+
libsystemd_static = static_library(
- 'systemd',
+ 'systemd_static',
libsystemd_sources,
install : false,
include_directories : includes,
link_with : libbasic,
dependencies : [threads,
librt],
- c_args : ['-fvisibility=default'])
+ c_args : libsystemd_c_args)
libsystemd_sym = 'src/libsystemd/libsystemd.sym'
diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c
index 07a1f50047..ff0790bf5a 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.c
+++ b/src/libsystemd/sd-bus/bus-common-errors.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
@@ -31,6 +13,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO),
+ SD_BUS_ERROR_MAP(BUS_ERROR_BAD_UNIT_SETTING, ENOEXEC),
SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_JOB, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_NOT_SUBSCRIBED, EINVAL),
@@ -72,6 +55,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_NTP_SUPPORT, EOPNOTSUPP),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS, ESRCH),
diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h
index 42c0f528f0..3945c7f6ac 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.h
+++ b/src/libsystemd/sd-bus/bus-common-errors.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-error.h"
@@ -27,6 +11,7 @@
#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID"
#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
+#define BUS_ERROR_BAD_UNIT_SETTING "org.freedesktop.systemd1.BadUnitSetting"
#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
@@ -54,6 +39,8 @@
#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping"
#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
+#define BUS_ERROR_NO_SUCH_PORTABLE_IMAGE "org.freedesktop.portable1.NoSuchImage"
+
#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
@@ -68,6 +55,7 @@
#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy"
#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
+#define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport"
#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c
index 477f7053ed..f50274a6a4 100644
--- a/src/libsystemd/sd-bus/bus-container.c
+++ b/src/libsystemd/sd-bus/bus-container.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <fcntl.h>
diff --git a/src/libsystemd/sd-bus/bus-container.h b/src/libsystemd/sd-bus/bus-container.h
index 6921ffd52d..dd115b4e24 100644
--- a/src/libsystemd/sd-bus/bus-container.h
+++ b/src/libsystemd/sd-bus/bus-container.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index 9dd5274bf6..18a2cc2c9b 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#if HAVE_VALGRIND_MEMCHECK_H
@@ -431,14 +415,11 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatabl
if (r < 0)
return r;
- *activatable = y;
- y = NULL;
+ *activatable = TAKE_PTR(y);
}
- if (acquired) {
- *acquired = x;
- x = NULL;
- }
+ if (acquired)
+ *acquired = TAKE_PTR(x);
return 0;
}
@@ -734,10 +715,8 @@ _public_ int sd_bus_get_name_creds(
return r;
}
- if (creds) {
- *creds = c;
- c = NULL;
- }
+ if (creds)
+ *creds = TAKE_PTR(c);
return 0;
}
@@ -810,8 +789,8 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
if (r < 0)
return r;
- *ret = c;
- c = NULL;
+ *ret = TAKE_PTR(c);
+
return 0;
}
diff --git a/src/libsystemd/sd-bus/bus-control.h b/src/libsystemd/sd-bus/bus-control.h
index 3d9acebaf6..9017297496 100644
--- a/src/libsystemd/sd-bus/bus-control.h
+++ b/src/libsystemd/sd-bus/bus-control.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c
index 8da6640ca0..41910515db 100644
--- a/src/libsystemd/sd-bus/bus-convenience.c
+++ b/src/libsystemd/sd-bus/bus-convenience.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-internal.h"
diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c
index b6ef4a0fe5..aae9fcd58b 100644
--- a/src/libsystemd/sd-bus/bus-creds.c
+++ b/src/libsystemd/sd-bus/bus-creds.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <linux/capability.h>
@@ -129,7 +113,6 @@ _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
sd_bus_message_unref(m);
}
-
return NULL;
}
@@ -222,7 +205,6 @@ _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
return 0;
}
-
_public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
assert_return(c, -EINVAL);
assert_return(fsuid, -EINVAL);
@@ -1344,7 +1326,7 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
if (r < 0)
return r;
- *ret = n;
- n = NULL;
+ *ret = TAKE_PTR(n);
+
return 0;
}
diff --git a/src/libsystemd/sd-bus/bus-creds.h b/src/libsystemd/sd-bus/bus-creds.h
index c4c60fa2d7..7b77a1d735 100644
--- a/src/libsystemd/sd-bus/bus-creds.h
+++ b/src/libsystemd/sd-bus/bus-creds.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index 2d93e1e437..3a28c7c6e3 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "alloc-util.h"
diff --git a/src/libsystemd/sd-bus/bus-dump.h b/src/libsystemd/sd-bus/bus-dump.h
index ab3b039203..8e47411a45 100644
--- a/src/libsystemd/sd-bus/bus-dump.h
+++ b/src/libsystemd/sd-bus/bus-dump.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c
index 3939d0a4ef..ec359ac13c 100644
--- a/src/libsystemd/sd-bus/bus-error.c
+++ b/src/libsystemd/sd-bus/bus-error.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
@@ -108,6 +92,7 @@ static int bus_error_name_to_errno(const char *name) {
}
m = __start_BUS_ERROR_MAP;
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
while (m < __stop_BUS_ERROR_MAP) {
/* For magic ELF error maps, the end marker might
* appear in the middle of things, since multiple maps
@@ -125,6 +110,7 @@ static int bus_error_name_to_errno(const char *name) {
m++;
}
+#endif
return EIO;
}
diff --git a/src/libsystemd/sd-bus/bus-error.h b/src/libsystemd/sd-bus/bus-error.h
index 6181e37d81..93cb9acd91 100644
--- a/src/libsystemd/sd-bus/bus-error.h
+++ b/src/libsystemd/sd-bus/bus-error.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
diff --git a/src/libsystemd/sd-bus/bus-gvariant.c b/src/libsystemd/sd-bus/bus-gvariant.c
index e6ab984d1f..05b17589dd 100644
--- a/src/libsystemd/sd-bus/bus-gvariant.c
+++ b/src/libsystemd/sd-bus/bus-gvariant.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
diff --git a/src/libsystemd/sd-bus/bus-gvariant.h b/src/libsystemd/sd-bus/bus-gvariant.h
index 474e131566..40e3053ec6 100644
--- a/src/libsystemd/sd-bus/bus-gvariant.h
+++ b/src/libsystemd/sd-bus/bus-gvariant.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "macro.h"
diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c
index 05a022fbf3..7bb653338d 100644
--- a/src/libsystemd/sd-bus/bus-internal.c
+++ b/src/libsystemd/sd-bus/bus-internal.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "alloc-util.h"
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index b305c41622..2087ef8eeb 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <pthread.h>
@@ -140,8 +124,17 @@ struct sd_bus_slot {
unsigned n_ref;
sd_bus *bus;
void *userdata;
+ sd_bus_destroy_t destroy_callback;
BusSlotType type:5;
+
+ /* Slots can be "floating" or not. If they are not floating (the usual case) then they reference the bus object
+ * they are associated with. This means the bus object stays allocated at least as long as there is a slot
+ * around associated with it. If it is floating, then the slot's lifecycle is bound to the lifecycle of the
+ * bus: it will be disconnected from the bus when the bus is destroyed, and it keeping the slot reffed hence
+ * won't mean the bus stays reffed too. Internally this means the reference direction is reversed: floating
+ * slots objects are referenced by the bus object, and not vice versa. */
bool floating:1;
+
bool match_added:1;
char *description;
@@ -278,7 +271,7 @@ struct sd_bus {
uint64_t creds_mask;
int *fds;
- unsigned n_fds;
+ size_t n_fds;
char *exec_path;
char **exec_argv;
@@ -338,7 +331,7 @@ struct sd_bus {
#define BUS_WQUEUE_MAX (192*1024)
#define BUS_RQUEUE_MAX (192*1024)
-#define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
+#define BUS_MESSAGE_SIZE_MAX (128*1024*1024)
#define BUS_AUTH_SIZE_MAX (64*1024)
#define BUS_CONTAINER_DEPTH 128
diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c
index 9bd2dadfde..cfcbd8b072 100644
--- a/src/libsystemd/sd-bus/bus-introspect.c
+++ b/src/libsystemd/sd-bus/bus-introspect.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdio_ext.h>
diff --git a/src/libsystemd/sd-bus/bus-introspect.h b/src/libsystemd/sd-bus/bus-introspect.h
index 5d2d5a17dd..5dcaeace9d 100644
--- a/src/libsystemd/sd-bus/bus-introspect.h
+++ b/src/libsystemd/sd-bus/bus-introspect.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdio.h>
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index b27b9d7d86..1f61bd3f95 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#if HAVE_VALGRIND_MEMCHECK_H
diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h
index fa78e5c80d..44c9a76311 100644
--- a/src/libsystemd/sd-bus/bus-kernel.h
+++ b/src/libsystemd/sd-bus/bus-kernel.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
index 8d798c0a58..7d04cc4bd1 100644
--- a/src/libsystemd/sd-bus/bus-match.c
+++ b/src/libsystemd/sd-bus/bus-match.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdio_ext.h>
@@ -903,12 +887,10 @@ int bus_match_parse(
}
components[n_components].type = t;
- components[n_components].value_str = value;
+ components[n_components].value_str = TAKE_PTR(value);
components[n_components].value_u8 = u;
n_components++;
- value = NULL;
-
if (q[quoted] == 0)
break;
diff --git a/src/libsystemd/sd-bus/bus-match.h b/src/libsystemd/sd-bus/bus-match.h
index ac2e51a422..050f4ba033 100644
--- a/src/libsystemd/sd-bus/bus-match.h
+++ b/src/libsystemd/sd-bus/bus-match.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index c76f6e87ba..8d92bc2002 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
@@ -109,7 +93,7 @@ static void message_reset_containers(sd_bus_message *m) {
m->root_container.index = 0;
}
-static void message_free(sd_bus_message *m) {
+static sd_bus_message* message_free(sd_bus_message *m) {
assert(m);
if (m->free_header)
@@ -134,9 +118,11 @@ static void message_free(sd_bus_message *m) {
free(m->root_container.peeked_signature);
bus_creds_done(&m->creds);
- free(m);
+ return mfree(m);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
+
static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
void *op, *np;
size_t old_size, new_size, start;
@@ -412,7 +398,7 @@ int bus_message_from_header(
size_t footer_accessible,
size_t message_size,
int *fds,
- unsigned n_fds,
+ size_t n_fds,
const char *label,
size_t extra,
sd_bus_message **ret) {
@@ -513,8 +499,7 @@ int bus_message_from_header(
}
m->bus = sd_bus_ref(bus);
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
@@ -524,11 +509,11 @@ int bus_message_from_malloc(
void *buffer,
size_t length,
int *fds,
- unsigned n_fds,
+ size_t n_fds,
const char *label,
sd_bus_message **ret) {
- sd_bus_message *m;
+ _cleanup_(message_freep) sd_bus_message *m = NULL;
size_t sz;
int r;
@@ -559,18 +544,14 @@ int bus_message_from_malloc(
r = bus_message_parse_fields(m);
if (r < 0)
- goto fail;
+ return r;
/* We take possession of the memory and fds now */
m->free_header = true;
m->free_fds = true;
- *ret = m;
+ *ret = TAKE_PTR(m);
return 0;
-
-fail:
- message_free(m);
- return r;
}
_public_ int sd_bus_message_new(
@@ -612,7 +593,7 @@ _public_ int sd_bus_message_new_signal(
const char *interface,
const char *member) {
- sd_bus_message *t;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
int r;
assert_return(bus, -ENOTCONN);
@@ -632,20 +613,16 @@ _public_ int sd_bus_message_new_signal(
r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
if (r < 0)
- goto fail;
+ return r;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- sd_bus_message_unref(t);
- return r;
}
_public_ int sd_bus_message_new_method_call(
@@ -656,7 +633,7 @@ _public_ int sd_bus_message_new_method_call(
const char *interface,
const char *member) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert_return(bus, -ENOTCONN);
@@ -675,29 +652,25 @@ _public_ int sd_bus_message_new_method_call(
r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
if (r < 0)
- goto fail;
+ return r;
if (interface) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
if (r < 0)
- goto fail;
+ return r;
}
if (destination) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
static int message_new_reply(
@@ -705,7 +678,7 @@ static int message_new_reply(
uint8_t type,
sd_bus_message **m) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
uint64_t cookie;
int r;
@@ -729,23 +702,19 @@ static int message_new_reply(
t->reply_cookie = cookie;
r = message_append_reply_cookie(t, t->reply_cookie);
if (r < 0)
- goto fail;
+ return r;
if (call->sender) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
t->enforced_reply_signature = call->enforced_reply_signature;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ int sd_bus_message_new_method_return(
@@ -760,7 +729,7 @@ _public_ int sd_bus_message_new_method_error(
sd_bus_message **m,
const sd_bus_error *e) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert_return(sd_bus_error_is_set(e), -EINVAL);
@@ -772,22 +741,18 @@ _public_ int sd_bus_message_new_method_error(
r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
if (r < 0)
- goto fail;
+ return r;
if (e->message) {
r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
if (r < 0)
- goto fail;
+ return r;
}
t->error._need_free = -1;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ int sd_bus_message_new_method_errorf(
@@ -867,7 +832,7 @@ int bus_message_new_synthetic_error(
const sd_bus_error *e,
sd_bus_message **m) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert(bus);
@@ -885,34 +850,30 @@ int bus_message_new_synthetic_error(
r = message_append_reply_cookie(t, t->reply_cookie);
if (r < 0)
- goto fail;
+ return r;
if (bus && bus->unique_name) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
if (r < 0)
- goto fail;
+ return r;
if (e->message) {
r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
if (r < 0)
- goto fail;
+ return r;
}
t->error._need_free = -1;
bus_message_set_sender_driver(bus, t);
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
@@ -937,8 +898,7 @@ _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
if (m->n_ref > 0)
return NULL;
- message_free(m);
- return NULL;
+ return message_free(m);
}
_public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
@@ -1085,10 +1045,10 @@ _public_ int sd_bus_message_is_signal(
if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
return 0;
- if (interface && (!m->interface || !streq(m->interface, interface)))
+ if (interface && !streq_ptr(m->interface, interface))
return 0;
- if (member && (!m->member || !streq(m->member, member)))
+ if (member && !streq_ptr(m->member, member))
return 0;
return 1;
@@ -1104,10 +1064,10 @@ _public_ int sd_bus_message_is_method_call(
if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
return 0;
- if (interface && (!m->interface || !streq(m->interface, interface)))
+ if (interface && !streq_ptr(m->interface, interface))
return 0;
- if (member && (!m->member || !streq(m->member, member)))
+ if (member && !streq_ptr(m->member, member))
return 0;
return 1;
@@ -1119,7 +1079,7 @@ _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name)
if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
return 0;
- if (name && (!m->error.name || !streq(m->error.name, name)))
+ if (name && !streq_ptr(m->error.name, name))
return 0;
return 1;
@@ -1665,7 +1625,7 @@ _public_ int sd_bus_message_append_string_space(
_public_ int sd_bus_message_append_string_iovec(
sd_bus_message *m,
const struct iovec *iov,
- unsigned n) {
+ unsigned n /* should be size_t, but is API now… 😞 */) {
size_t size;
unsigned i;
@@ -1991,7 +1951,7 @@ _public_ int sd_bus_message_open_container(
struct bus_container *c, *w;
uint32_t *array_size = NULL;
- char *signature;
+ _cleanup_free_ char *signature = NULL;
size_t before, begin = 0;
bool need_offsets = false;
int r;
@@ -2030,16 +1990,13 @@ _public_ int sd_bus_message_open_container(
r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
else
r = -EINVAL;
-
- if (r < 0) {
- free(signature);
+ if (r < 0)
return r;
- }
/* OK, let's fill it in */
w = m->containers + m->n_containers++;
w->enclosing = type;
- w->signature = signature;
+ w->signature = TAKE_PTR(signature);
w->index = 0;
w->array_size = array_size;
w->before = before;
@@ -2589,7 +2546,7 @@ _public_ int sd_bus_message_append_array_iovec(
sd_bus_message *m,
char type,
const struct iovec *iov,
- unsigned n) {
+ unsigned n /* should be size_t, but is API now… 😞 */) {
size_t size;
unsigned i;
@@ -3235,7 +3192,6 @@ end:
return 0;
}
-
static int message_peek_body(
sd_bus_message *m,
size_t *rindex,
@@ -4012,9 +3968,9 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m,
const char *contents) {
struct bus_container *c, *w;
uint32_t *array_size = NULL;
- char *signature;
+ _cleanup_free_ char *signature = NULL;
size_t before;
- size_t *offsets = NULL;
+ _cleanup_free_ size_t *offsets = NULL;
size_t n_offsets = 0, item_size = 0;
int r;
@@ -4088,17 +4044,13 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m,
r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
else
r = -EINVAL;
-
- if (r <= 0) {
- free(signature);
- free(offsets);
+ if (r <= 0)
return r;
- }
/* OK, let's fill it in */
w = m->containers + m->n_containers++;
w->enclosing = type;
- w->signature = signature;
+ w->signature = TAKE_PTR(signature);
w->peeked_signature = NULL;
w->index = 0;
@@ -4115,7 +4067,7 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m,
w->array_size = array_size;
w->item_size = item_size;
- w->offsets = offsets;
+ w->offsets = TAKE_PTR(offsets);
w->n_offsets = n_offsets;
w->offset_index = 0;
@@ -4384,7 +4336,7 @@ static int message_read_ap(
/* Ideally, we'd just call ourselves recursively on every
* complex type. However, the state of a va_list that is
* passed to a function is undefined after that function
- * returns. This means we need to docode the va_list linearly
+ * returns. This means we need to decode the va_list linearly
* in a single stackframe. We hence implement our own
* home-grown stack in an array. */
@@ -5329,7 +5281,6 @@ int bus_message_parse_fields(sd_bus_message *m) {
break;
-
case BUS_MESSAGE_HEADER_SIGNATURE: {
const char *s;
char *c;
@@ -5351,8 +5302,7 @@ int bus_message_parse_fields(sd_bus_message *m) {
if (!c)
return -ENOMEM;
- free(m->root_container.signature);
- m->root_container.signature = c;
+ free_and_replace(m->root_container.signature, c);
break;
}
@@ -5501,7 +5451,7 @@ _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
size_t total;
void *p, *e;
- unsigned i;
+ size_t i;
struct bus_body_part *part;
assert(m);
@@ -5553,7 +5503,7 @@ int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
}
_public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
- char **strv = NULL;
+ _cleanup_strv_free_ char **strv = NULL;
int r;
assert_return(m, -EINVAL);
@@ -5561,12 +5511,10 @@ _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
assert_return(l, -EINVAL);
r = bus_message_read_strv_extend(m, &strv);
- if (r <= 0) {
- strv_free(strv);
+ if (r <= 0)
return r;
- }
- *l = strv;
+ *l = TAKE_PTR(strv);
return 1;
}
@@ -5869,8 +5817,7 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
return r;
sd_bus_message_unref(*m);
- *m = n;
- n = NULL;
+ *m = TAKE_PTR(n);
return 0;
}
diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h
index 88998700d6..97f6060e30 100644
--- a/src/libsystemd/sd-bus/bus-message.h
+++ b/src/libsystemd/sd-bus/bus-message.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <byteswap.h>
@@ -195,7 +179,7 @@ int bus_message_from_header(
size_t footer_accessible,
size_t message_size,
int *fds,
- unsigned n_fds,
+ size_t n_fds,
const char *label,
size_t extra,
sd_bus_message **ret);
@@ -205,7 +189,7 @@ int bus_message_from_malloc(
void *buffer,
size_t length,
int *fds,
- unsigned n_fds,
+ size_t n_fds,
const char *label,
sd_bus_message **ret);
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index 6e00255b20..9609834fa9 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "alloc-util.h"
@@ -173,9 +157,9 @@ static int add_enumerated_to_set(
enum {
/* if set, add_subtree() works recursively */
- CHILDREN_RECURSIVE = (1U << 1),
+ CHILDREN_RECURSIVE = 1 << 0,
/* if set, add_subtree() scans object-manager hierarchies recursively */
- CHILDREN_SUBHIERARCHIES = (1U << 0),
+ CHILDREN_SUBHIERARCHIES = 1 << 1,
};
static int add_subtree_to_set(
@@ -1470,8 +1454,7 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
return NULL;
n->parent = parent;
- n->path = s;
- s = NULL; /* do not free */
+ n->path = TAKE_PTR(s);
r = hashmap_put(bus->nodes, n->path, n);
if (r < 0) {
diff --git a/src/libsystemd/sd-bus/bus-objects.h b/src/libsystemd/sd-bus/bus-objects.h
index 6bffeda726..e8e1a522cb 100644
--- a/src/libsystemd/sd-bus/bus-objects.h
+++ b/src/libsystemd/sd-bus/bus-objects.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-internal.h"
diff --git a/src/libsystemd/sd-bus/bus-protocol.h b/src/libsystemd/sd-bus/bus-protocol.h
index 0d5dfd9474..20d19d4022 100644
--- a/src/libsystemd/sd-bus/bus-protocol.h
+++ b/src/libsystemd/sd-bus/bus-protocol.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <endian.h>
diff --git a/src/libsystemd/sd-bus/bus-signature.c b/src/libsystemd/sd-bus/bus-signature.c
index f3cd9bd0fa..18c91e8707 100644
--- a/src/libsystemd/sd-bus/bus-signature.c
+++ b/src/libsystemd/sd-bus/bus-signature.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <util.h>
@@ -109,7 +93,6 @@ static int signature_element_length_internal(
return -EINVAL;
}
-
int signature_element_length(const char *s, size_t *l) {
return signature_element_length_internal(s, true, 0, 0, l);
}
diff --git a/src/libsystemd/sd-bus/bus-signature.h b/src/libsystemd/sd-bus/bus-signature.h
index a6be1844e2..d4b43bac00 100644
--- a/src/libsystemd/sd-bus/bus-signature.h
+++ b/src/libsystemd/sd-bus/bus-signature.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
index 9a56371715..fbf37320d3 100644
--- a/src/libsystemd/sd-bus/bus-slot.c
+++ b/src/libsystemd/sd-bus/bus-slot.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
@@ -170,7 +154,6 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
key.interface = slot->node_vtable.interface;
key.member = v->x.method.member;
-
x = hashmap_remove(slot->bus->vtable_properties, &key);
break;
}}
@@ -217,6 +200,10 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
}
bus_slot_disconnect(slot);
+
+ if (slot->destroy_callback)
+ slot->destroy_callback(slot->userdata);
+
free(slot->description);
return mfree(slot);
}
@@ -244,6 +231,22 @@ _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
return ret;
}
+_public_ int sd_bus_slot_set_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t callback) {
+ assert_return(slot, -EINVAL);
+
+ slot->destroy_callback = callback;
+ return 0;
+}
+
+_public_ int sd_bus_slot_get_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t *callback) {
+ assert_return(slot, -EINVAL);
+
+ if (callback)
+ *callback = slot->destroy_callback;
+
+ return !!slot->destroy_callback;
+}
+
_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
assert_return(slot, NULL);
assert_return(slot->type >= 0, NULL);
@@ -274,6 +277,37 @@ _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
return slot->bus->current_userdata;
}
+_public_ int sd_bus_slot_get_floating(sd_bus_slot *slot) {
+ assert_return(slot, -EINVAL);
+
+ return slot->floating;
+}
+
+_public_ int sd_bus_slot_set_floating(sd_bus_slot *slot, int b) {
+ assert_return(slot, -EINVAL);
+
+ if (slot->floating == !!b)
+ return 0;
+
+ if (!slot->bus) /* already disconnected slots can't be reconnected */
+ return -ESTALE;
+
+ slot->floating = b;
+
+ /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence,
+ * when we move from one to the other, let's increase one reference and decrease the other. */
+
+ if (b) {
+ sd_bus_slot_ref(slot);
+ sd_bus_unref(slot->bus);
+ } else {
+ sd_bus_ref(slot->bus);
+ sd_bus_slot_unref(slot);
+ }
+
+ return 1;
+}
+
_public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
assert_return(slot, -EINVAL);
@@ -283,8 +317,13 @@ _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *descript
_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
assert_return(slot, -EINVAL);
assert_return(description, -EINVAL);
- assert_return(slot->description, -ENXIO);
- *description = slot->description;
+ if (slot->description)
+ *description = slot->description;
+ else if (slot->type == BUS_MATCH_CALLBACK)
+ *description = slot->match_callback.match_string;
+ else
+ return -ENXIO;
+
return 0;
}
diff --git a/src/libsystemd/sd-bus/bus-slot.h b/src/libsystemd/sd-bus/bus-slot.h
index beebaa1670..f1e1e23ac6 100644
--- a/src/libsystemd/sd-bus/bus-slot.h
+++ b/src/libsystemd/sd-bus/bus-slot.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 082688b17e..b147a3843a 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <endian.h>
@@ -261,16 +245,13 @@ static bool line_equals(const char *s, size_t m, const char *line) {
}
static bool line_begins(const char *s, size_t m, const char *word) {
- size_t l;
-
- l = strlen(word);
- if (m < l)
- return false;
+ const char *p;
- if (memcmp(s, word, l) != 0)
+ p = memory_startswith(s, m, word);
+ if (!p)
return false;
- return m == l || (m > l && s[l] == ' ');
+ return IN_SET(*p, 0, ' ');
}
static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
@@ -552,7 +533,7 @@ static int bus_socket_read_auth(sd_bus *b) {
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
- k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
+ k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (k < 0 && errno == ENOTSOCK) {
b->prefer_readv = true;
k = readv(b->input_fd, &iov, 1);
@@ -790,7 +771,7 @@ static int bus_socket_inotify_setup(sd_bus *b) {
if (IN_SET(errno, ENOENT, ELOOP))
break; /* This component doesn't exist yet, or the path contains a cyclic symlink right now */
- r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", isempty(prefix) ? "/" : prefix);
+ r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", empty_to_root(prefix));
goto fail;
} else
new_watches[n++] = wd;
@@ -1182,7 +1163,7 @@ int bus_socket_read_message(sd_bus *bus) {
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
- k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
+ k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (k < 0 && errno == ENOTSOCK) {
bus->prefer_readv = true;
k = readv(bus->input_fd, &iov, 1);
diff --git a/src/libsystemd/sd-bus/bus-socket.h b/src/libsystemd/sd-bus/bus-socket.h
index c180562f98..d1118ca1d4 100644
--- a/src/libsystemd/sd-bus/bus-socket.h
+++ b/src/libsystemd/sd-bus/bus-socket.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index 5482d39a01..16bf615f50 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
@@ -44,6 +28,7 @@ struct sd_bus_track {
bool in_queue:1; /* In bus->track_queue? */
bool modified:1;
bool recursive:1;
+ sd_bus_destroy_t destroy_callback;
LIST_FIELDS(sd_bus_track, tracks);
};
@@ -177,18 +162,21 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
return NULL;
assert(track->n_ref > 0);
+ track->n_ref--;
- if (track->n_ref > 1) {
- track->n_ref--;
+ if (track->n_ref > 0)
return NULL;
- }
if (track->in_list)
LIST_REMOVE(tracks, track->bus->tracks, track);
bus_track_remove_from_queue(track);
- hashmap_free_with_destructor(track->names, track_item_free);
- sd_bus_unref(track->bus);
+ track->names = hashmap_free_with_destructor(track->names, track_item_free);
+ track->bus = sd_bus_unref(track->bus);
+
+ if (track->destroy_callback)
+ track->destroy_callback(track->userdata);
+
return mfree(track);
}
@@ -452,6 +440,22 @@ _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) {
return ret;
}
+_public_ int sd_bus_track_set_destroy_callback(sd_bus_track *track, sd_bus_destroy_t callback) {
+ assert_return(track, -EINVAL);
+
+ track->destroy_callback = callback;
+ return 0;
+}
+
+_public_ int sd_bus_track_get_destroy_callback(sd_bus_track *track, sd_bus_destroy_t *ret) {
+ assert_return(track, -EINVAL);
+
+ if (ret)
+ *ret = track->destroy_callback;
+
+ return !!track->destroy_callback;
+}
+
_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) {
assert_return(track, -EINVAL);
diff --git a/src/libsystemd/sd-bus/bus-track.h b/src/libsystemd/sd-bus/bus-track.h
index 0c5636b7e0..f9590265d7 100644
--- a/src/libsystemd/sd-bus/bus-track.h
+++ b/src/libsystemd/sd-bus/bus-track.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
void bus_track_dispatch(sd_bus_track *track);
diff --git a/src/libsystemd/sd-bus/bus-type.c b/src/libsystemd/sd-bus/bus-type.c
index 980b35d8ea..bc6726f9cf 100644
--- a/src/libsystemd/sd-bus/bus-type.c
+++ b/src/libsystemd/sd-bus/bus-type.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
diff --git a/src/libsystemd/sd-bus/bus-type.h b/src/libsystemd/sd-bus/bus-type.h
index 834f09777a..cdac55c62e 100644
--- a/src/libsystemd/sd-bus/bus-type.h
+++ b/src/libsystemd/sd-bus/bus-type.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 2f5e483ae2..089b51a6d9 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <endian.h>
@@ -176,7 +160,7 @@ static void bus_reset_queues(sd_bus *b) {
b->wqueue_allocated = 0;
}
-static void bus_free(sd_bus *b) {
+static sd_bus* bus_free(sd_bus *b) {
sd_bus_slot *s;
assert(b);
@@ -241,56 +225,47 @@ static void bus_free(sd_bus *b) {
assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
- free(b);
+ return mfree(b);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, bus_free);
+
_public_ int sd_bus_new(sd_bus **ret) {
- sd_bus *r;
+ _cleanup_free_ sd_bus *b = NULL;
assert_return(ret, -EINVAL);
- r = new0(sd_bus, 1);
- if (!r)
+ b = new0(sd_bus, 1);
+ if (!b)
return -ENOMEM;
- r->n_ref = REFCNT_INIT;
- r->input_fd = r->output_fd = -1;
- r->inotify_fd = -1;
- r->message_version = 1;
- r->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
- r->accept_fd = true;
- r->original_pid = getpid_cached();
- r->n_groups = (size_t) -1;
-
- assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
-
- /* We guarantee that wqueue always has space for at least one
- * entry */
- if (!GREEDY_REALLOC(r->wqueue, r->wqueue_allocated, 1)) {
- free(r);
+ b->n_ref = REFCNT_INIT;
+ b->input_fd = b->output_fd = -1;
+ b->inotify_fd = -1;
+ b->message_version = 1;
+ b->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
+ b->accept_fd = true;
+ b->original_pid = getpid_cached();
+ b->n_groups = (size_t) -1;
+
+ assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
+
+ /* We guarantee that wqueue always has space for at least one entry */
+ if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1))
return -ENOMEM;
- }
- *ret = r;
+ *ret = TAKE_PTR(b);
return 0;
}
_public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
- char *a;
-
assert_return(bus, -EINVAL);
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(address, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- a = strdup(address);
- if (!a)
- return -ENOMEM;
-
- free_and_replace(bus->address, a);
-
- return 0;
+ return free_and_strdup(&bus->address, address);
}
_public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
@@ -307,7 +282,8 @@ _public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
}
_public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
- char *p, **a;
+ _cleanup_strv_free_ char **a = NULL;
+ int r;
assert_return(bus, -EINVAL);
assert_return(bus = bus_resolve(bus), -ENOPKG);
@@ -316,22 +292,15 @@ _public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[])
assert_return(!strv_isempty(argv), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- p = strdup(path);
- if (!p)
- return -ENOMEM;
-
a = strv_copy(argv);
- if (!a) {
- free(p);
+ if (!a)
return -ENOMEM;
- }
-
- free_and_replace(bus->exec_path, p);
- strv_free(bus->exec_argv);
- bus->exec_argv = a;
+ r = free_and_strdup(&bus->exec_path, path);
+ if (r < 0)
+ return r;
- return 0;
+ return strv_free_and_replace(bus->exec_argv, a);
}
_public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
@@ -524,8 +493,7 @@ static int synthesize_connected_signal(sd_bus *bus) {
/* Insert at the very front */
memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size);
- bus->rqueue[0] = m;
- m = NULL;
+ bus->rqueue[0] = TAKE_PTR(m);
bus->rqueue_size++;
return 0;
@@ -556,7 +524,6 @@ void bus_set_state(sd_bus *bus, enum bus_state state) {
static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
const char *s;
- char *t;
sd_bus *bus;
int r;
@@ -576,11 +543,9 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e
if (!service_name_is_valid(s) || s[0] != ':')
return -EBADMSG;
- t = strdup(s);
- if (!t)
- return -ENOMEM;
-
- free_and_replace(bus->unique_name, t);
+ r = free_and_strdup(&bus->unique_name, s);
+ if (r < 0)
+ return r;
if (bus->state == BUS_HELLO) {
bus_set_state(bus, BUS_RUNNING);
@@ -1220,9 +1185,9 @@ _public_ int sd_bus_start(sd_bus *bus) {
return bus_send_hello(bus);
}
-_public_ int sd_bus_open(sd_bus **ret) {
+_public_ int sd_bus_open_with_description(sd_bus **ret, const char *description) {
const char *e;
- sd_bus *b;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
@@ -1234,17 +1199,17 @@ _public_ int sd_bus_open(sd_bus **ret) {
e = secure_getenv("DBUS_STARTER_BUS_TYPE");
if (e) {
if (streq(e, "system"))
- return sd_bus_open_system(ret);
+ return sd_bus_open_system_with_description(ret, description);
else if (STR_IN_SET(e, "session", "user"))
- return sd_bus_open_user(ret);
+ return sd_bus_open_user_with_description(ret, description);
}
e = secure_getenv("DBUS_STARTER_ADDRESS");
if (!e) {
if (cg_pid_get_owner_uid(0, NULL) >= 0)
- return sd_bus_open_user(ret);
+ return sd_bus_open_user_with_description(ret, description);
else
- return sd_bus_open_system(ret);
+ return sd_bus_open_system_with_description(ret, description);
}
r = sd_bus_new(&b);
@@ -1253,7 +1218,7 @@ _public_ int sd_bus_open(sd_bus **ret) {
r = sd_bus_set_address(b, e);
if (r < 0)
- goto fail;
+ return r;
b->bus_client = true;
@@ -1265,14 +1230,14 @@ _public_ int sd_bus_open(sd_bus **ret) {
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
+}
-fail:
- bus_free(b);
- return r;
+_public_ int sd_bus_open(sd_bus **ret) {
+ return sd_bus_open_with_description(ret, NULL);
}
int bus_set_address_system(sd_bus *b) {
@@ -1286,8 +1251,8 @@ int bus_set_address_system(sd_bus *b) {
return sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_ADDRESS);
}
-_public_ int sd_bus_open_system(sd_bus **ret) {
- sd_bus *b;
+_public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *description) {
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
@@ -1296,9 +1261,15 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
if (r < 0)
return r;
+ if (description) {
+ r = sd_bus_set_description(b, description);
+ if (r < 0)
+ return r;
+ }
+
r = bus_set_address_system(b);
if (r < 0)
- goto fail;
+ return r;
b->bus_client = true;
b->is_system = true;
@@ -1311,14 +1282,14 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
+}
-fail:
- bus_free(b);
- return r;
+_public_ int sd_bus_open_system(sd_bus **ret) {
+ return sd_bus_open_system_with_description(ret, NULL);
}
int bus_set_address_user(sd_bus *b) {
@@ -1342,14 +1313,13 @@ int bus_set_address_user(sd_bus *b) {
if (asprintf(&s, DEFAULT_USER_BUS_ADDRESS_FMT, ee) < 0)
return -ENOMEM;
- b->address = s;
- s = NULL;
+ b->address = TAKE_PTR(s);
return 0;
}
-_public_ int sd_bus_open_user(sd_bus **ret) {
- sd_bus *b;
+_public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *description) {
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
@@ -1358,9 +1328,15 @@ _public_ int sd_bus_open_user(sd_bus **ret) {
if (r < 0)
return r;
+ if (description) {
+ r = sd_bus_set_description(b, description);
+ if (r < 0)
+ return r;
+ }
+
r = bus_set_address_user(b);
if (r < 0)
- goto fail;
+ return r;
b->bus_client = true;
b->is_user = true;
@@ -1372,14 +1348,14 @@ _public_ int sd_bus_open_user(sd_bus **ret) {
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
+}
-fail:
- bus_free(b);
- return r;
+_public_ int sd_bus_open_user(sd_bus **ret) {
+ return sd_bus_open_user_with_description(ret, NULL);
}
int bus_set_address_system_remote(sd_bus *b, const char *host) {
@@ -1396,7 +1372,7 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) {
/* Let's make sure this is not a port of some kind,
* and is a valid machine name. */
- if (!in_charset(m, "0123456789") && machine_name_is_valid(m)) {
+ if (!in_charset(m, DIGITS) && machine_name_is_valid(m)) {
char *t;
/* Cut out the host part */
@@ -1419,41 +1395,35 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) {
if (!a)
return -ENOMEM;
- free_and_replace(b->address, a);
-
- return 0;
- }
+ return free_and_replace(b->address, a);
+}
_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
- sd_bus *bus;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(host, -EINVAL);
assert_return(ret, -EINVAL);
- r = sd_bus_new(&bus);
+ r = sd_bus_new(&b);
if (r < 0)
return r;
- r = bus_set_address_system_remote(bus, host);
+ r = bus_set_address_system_remote(b, host);
if (r < 0)
- goto fail;
+ return r;
- bus->bus_client = true;
- bus->trusted = false;
- bus->is_system = true;
- bus->is_local = false;
+ b->bus_client = true;
+ b->trusted = false;
+ b->is_system = true;
+ b->is_local = false;
- r = sd_bus_start(bus);
+ r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = bus;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(bus);
- return r;
}
int bus_set_address_system_machine(sd_bus *b, const char *machine) {
@@ -1471,46 +1441,39 @@ int bus_set_address_system_machine(sd_bus *b, const char *machine) {
if (!a)
return -ENOMEM;
- free_and_replace(b->address, a);
-
- return 0;
+ return free_and_replace(b->address, a);
}
_public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) {
- sd_bus *bus;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(machine, -EINVAL);
assert_return(ret, -EINVAL);
assert_return(machine_name_is_valid(machine), -EINVAL);
- r = sd_bus_new(&bus);
+ r = sd_bus_new(&b);
if (r < 0)
return r;
- r = bus_set_address_system_machine(bus, machine);
+ r = bus_set_address_system_machine(b, machine);
if (r < 0)
- goto fail;
+ return r;
- bus->bus_client = true;
- bus->trusted = false;
- bus->is_system = true;
- bus->is_local = false;
+ b->bus_client = true;
+ b->trusted = false;
+ b->is_system = true;
+ b->is_local = false;
- r = sd_bus_start(bus);
+ r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = bus;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(bus);
- return r;
}
_public_ void sd_bus_close(sd_bus *bus) {
-
if (!bus)
return;
if (bus->state == BUS_CLOSED)
@@ -1534,7 +1497,6 @@ _public_ void sd_bus_close(sd_bus *bus) {
}
_public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
-
if (!bus)
return NULL;
@@ -1557,7 +1519,6 @@ void bus_enter_closing(sd_bus *bus) {
}
_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
-
if (!bus)
return NULL;
@@ -1576,12 +1537,10 @@ _public_ sd_bus *sd_bus_unref(sd_bus *bus) {
if (i > 0)
return NULL;
- bus_free(bus);
- return NULL;
+ return bus_free(bus);
}
_public_ int sd_bus_is_open(sd_bus *bus) {
-
assert_return(bus, -EINVAL);
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2752,8 +2711,8 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd
if (r < 0)
return r;
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
+
return 1;
}
@@ -2912,10 +2871,8 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
bus->exit_triggered = true;
(void) bus_exit_now(bus);
- if (ret) {
- *ret = m;
- m = NULL;
- }
+ if (ret)
+ *ret = TAKE_PTR(m);
r = 1;
@@ -3267,13 +3224,21 @@ static int bus_add_match_full(
goto finish;
}
- if (asynchronous)
+ if (asynchronous) {
r = bus_add_match_internal_async(bus,
&s->match_callback.install_slot,
s->match_callback.match_string,
add_match_callback,
s);
- else
+
+ if (r < 0)
+ return r;
+
+ /* Make the slot of the match call floating now. We need the reference, but we don't
+ * want that this match pins the bus object, hence we first create it non-floating, but
+ * then make it floating. */
+ r = sd_bus_slot_set_floating(s->match_callback.install_slot, true);
+ } else
r = bus_add_match_internal(bus, s->match_callback.match_string);
if (r < 0)
goto finish;
@@ -3670,7 +3635,6 @@ _public_ int sd_bus_default_system(sd_bus **ret) {
return bus_default(sd_bus_open_system, &default_system_bus, ret);
}
-
_public_ int sd_bus_default_user(sd_bus **ret) {
return bus_default(sd_bus_open_user, &default_user_bus, ret);
}
diff --git a/src/libsystemd/sd-bus/test-bus-benchmark.c b/src/libsystemd/sd-bus/test-bus-benchmark.c
index bfd0f39372..8134abba2f 100644
--- a/src/libsystemd/sd-bus/test-bus-benchmark.c
+++ b/src/libsystemd/sd-bus/test-bus-benchmark.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/wait.h>
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index bd6721946a..1e25e94586 100644
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <fcntl.h>
@@ -64,11 +48,11 @@ static int server_init(sd_bus **_bus) {
sd_bus *bus = NULL;
sd_id128_t id;
int r;
- const char *unique;
+ const char *unique, *desc;
assert_se(_bus);
- r = sd_bus_open_user(&bus);
+ r = sd_bus_open_user_with_description(&bus, "my bus!");
if (r < 0) {
log_error_errno(r, "Failed to connect to user bus: %m");
goto fail;
@@ -86,6 +70,9 @@ static int server_init(sd_bus **_bus) {
goto fail;
}
+ r = sd_bus_get_description(bus, &desc);
+ assert_se(streq(desc, "my bus!"));
+
log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
log_info("Unique ID: %s", unique);
log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
diff --git a/src/libsystemd/sd-bus/test-bus-cleanup.c b/src/libsystemd/sd-bus/test-bus-cleanup.c
index d5601fc57b..d1d962ebb2 100644
--- a/src/libsystemd/sd-bus/test-bus-cleanup.c
+++ b/src/libsystemd/sd-bus/test-bus-cleanup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c
index f654692bf6..6746c0973e 100644
--- a/src/libsystemd/sd-bus/test-bus-creds.c
+++ b/src/libsystemd/sd-bus/test-bus-creds.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c
index 4e3f404e68..250657b18e 100644
--- a/src/libsystemd/sd-bus/test-bus-error.c
+++ b/src/libsystemd/sd-bus/test-bus-error.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c
index 4c372fd05a..75804f3458 100644
--- a/src/libsystemd/sd-bus/test-bus-gvariant.c
+++ b/src/libsystemd/sd-bus/test-bus-gvariant.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#if HAVE_GLIB
diff --git a/src/libsystemd/sd-bus/test-bus-introspect.c b/src/libsystemd/sd-bus/test-bus-introspect.c
index 8dee936768..00167cb643 100644
--- a/src/libsystemd/sd-bus/test-bus-introspect.c
+++ b/src/libsystemd/sd-bus/test-bus-introspect.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-introspect.h"
diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c
index ebf55e873c..c647f0ff12 100644
--- a/src/libsystemd/sd-bus/test-bus-marshal.c
+++ b/src/libsystemd/sd-bus/test-bus-marshal.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <math.h>
@@ -217,6 +201,7 @@ int main(int argc, char *argv[]) {
free(h);
#if HAVE_GLIB
+#ifndef __SANITIZE_ADDRESS__
{
GDBusMessage *g;
char *p;
@@ -232,6 +217,7 @@ int main(int argc, char *argv[]) {
g_object_unref(g);
}
#endif
+#endif
#if HAVE_DBUS
{
diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c
index 47b45647c2..2822a8f82a 100644
--- a/src/libsystemd/sd-bus/test-bus-match.c
+++ b/src/libsystemd/sd-bus/test-bus-match.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-match.h"
diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c
index 58ef8b6389..094dd6c8a0 100644
--- a/src/libsystemd/sd-bus/test-bus-objects.c
+++ b/src/libsystemd/sd-bus/test-bus-objects.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <pthread.h>
diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c
index 245f5707e1..31b54e252c 100644
--- a/src/libsystemd/sd-bus/test-bus-server.c
+++ b/src/libsystemd/sd-bus/test-bus-server.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <pthread.h>
@@ -81,7 +65,8 @@ static void *server(void *p) {
if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
- assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
+ assert_se((sd_bus_can_send(bus, 'h') >= 1) ==
+ (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0) {
diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c
index aa6160d1c9..1ba1909198 100644
--- a/src/libsystemd/sd-bus/test-bus-signature.c
+++ b/src/libsystemd/sd-bus/test-bus-signature.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-internal.h"
diff --git a/src/libsystemd/sd-bus/test-bus-track.c b/src/libsystemd/sd-bus/test-bus-track.c
index 94c9d09de3..48d708b258 100644
--- a/src/libsystemd/sd-bus/test-bus-track.c
+++ b/src/libsystemd/sd-bus/test-bus-track.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
diff --git a/src/libsystemd/sd-bus/test-bus-watch-bind.c b/src/libsystemd/sd-bus/test-bus-watch-bind.c
index aef5ba9486..42a9ce5301 100644
--- a/src/libsystemd/sd-bus/test-bus-watch-bind.c
+++ b/src/libsystemd/sd-bus/test-bus-watch-bind.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <pthread.h>
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 1334498ca4..9e9b115557 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
@@ -141,8 +125,7 @@ _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
return r;
}
- *names = l;
- l = NULL;
+ *names = TAKE_PTR(l);
return n_fds;
}
diff --git a/src/libsystemd/sd-device/device-enumerator-private.h b/src/libsystemd/sd-device/device-enumerator-private.h
index 5a46ec5f2b..5d58ac93ca 100644
--- a/src/libsystemd/sd-device/device-enumerator-private.h
+++ b/src/libsystemd/sd-device/device-enumerator-private.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-device.h"
diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c
index cd9ec042bf..ee71fa8810 100644
--- a/src/libsystemd/sd-device/device-enumerator.c
+++ b/src/libsystemd/sd-device/device-enumerator.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2014-2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-device.h"
@@ -71,8 +52,7 @@ _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
enumerator->n_ref = 1;
enumerator->type = _DEVICE_ENUMERATION_TYPE_INVALID;
- *ret = enumerator;
- enumerator = NULL;
+ *ret = TAKE_PTR(enumerator);
return 0;
}
diff --git a/src/libsystemd/sd-device/device-internal.h b/src/libsystemd/sd-device/device-internal.h
index 6be84f9575..64da0501fe 100644
--- a/src/libsystemd/sd-device/device-internal.h
+++ b/src/libsystemd/sd-device/device-internal.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "hashmap.h"
#include "set.h"
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index 77f0f4b2ee..d1f1b085ac 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <net/if.h>
@@ -586,8 +567,7 @@ int device_new_from_strv(sd_device **ret, char **strv) {
if (r < 0)
return r;
- *ret = device;
- device = NULL;
+ *ret = TAKE_PTR(device);
return 0;
}
@@ -635,8 +615,7 @@ int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
if (r < 0)
return r;
- *ret = device;
- device = NULL;
+ *ret = TAKE_PTR(device);
return 0;
}
@@ -812,8 +791,7 @@ int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
ret->devnum = old_device->devnum;
- *new_device = ret;
- ret = NULL;
+ *new_device = TAKE_PTR(ret);
return 0;
}
@@ -835,8 +813,7 @@ int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
ret->sealed = true;
- *new_device = ret;
- ret = NULL;
+ *new_device = TAKE_PTR(ret);
return 0;
}
@@ -861,8 +838,7 @@ int device_new_from_synthetic_event(sd_device **new_device, const char *syspath,
if (r < 0)
return r;
- *new_device = ret;
- ret = NULL;
+ *new_device = TAKE_PTR(ret);
return 0;
}
diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h
index 02d93c98f9..800c9ba7bd 100644
--- a/src/libsystemd/sd-device/device-private.h
+++ b/src/libsystemd/sd-device/device-private.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <inttypes.h>
#include <stdbool.h>
diff --git a/src/libsystemd/sd-device/device-util.h b/src/libsystemd/sd-device/device-util.h
index d55b810d2a..6dcd2645e6 100644
--- a/src/libsystemd/sd-device/device-util.h
+++ b/src/libsystemd/sd-device/device-util.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014-2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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"
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index 1297dfa911..be29053f8c 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <net/if.h>
@@ -46,7 +27,7 @@
#include "util.h"
int device_new_aux(sd_device **ret) {
- _cleanup_(sd_device_unrefp) sd_device *device = NULL;
+ sd_device *device = NULL;
assert(ret);
@@ -58,7 +39,6 @@ int device_new_aux(sd_device **ret) {
device->watch_handle = -1;
*ret = device;
- device = NULL;
return 0;
}
@@ -168,12 +148,9 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
if (verify) {
r = chase_symlinks(_syspath, NULL, 0, &syspath);
if (r == -ENOENT)
- /* the device does not exist (any more?) */
- return -ENODEV;
- else if (r < 0) {
- log_debug_errno(r, "sd-device: could not get target of '%s': %m", _syspath);
- return r;
- }
+ return -ENODEV; /* the device does not exist (any more?) */
+ if (r < 0)
+ return log_debug_errno(r, "sd-device: could not get target of '%s': %m", _syspath);
if (!path_startswith(syspath, "/sys")) {
_cleanup_free_ char *real_sys = NULL, *new_syspath = NULL;
@@ -195,7 +172,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
return log_oom();
free_and_replace(syspath, new_syspath);
- path_kill_slashes(syspath);
+ path_simplify(syspath, false);
}
if (path_startswith(syspath, "/sys/devices/")) {
@@ -250,8 +227,7 @@ _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
if (r < 0)
return r;
- *ret = device;
- device = NULL;
+ *ret = TAKE_PTR(device);
return 0;
}
@@ -662,8 +638,7 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
if (ifr.ifr_ifindex != ifindex)
return -ENODEV;
- *ret = device;
- device = NULL;
+ *ret = TAKE_PTR(device);
return 0;
}
@@ -1297,8 +1272,7 @@ int device_get_id_filename(sd_device *device, const char **ret) {
}
}
- device->id_filename = id;
- id = NULL;
+ device->id_filename = TAKE_PTR(id);
}
*ret = device->id_filename;
@@ -1837,8 +1811,7 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
if (r < 0)
return r;
- *_value = value;
- value = NULL;
+ *_value = TAKE_PTR(value);
return 0;
}
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 7355921d30..d53b9a7026 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/epoll.h>
@@ -28,6 +12,7 @@
#include "alloc-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "list.h"
#include "macro.h"
@@ -56,6 +41,7 @@ typedef enum EventSourceType {
SOURCE_POST,
SOURCE_EXIT,
SOURCE_WATCHDOG,
+ SOURCE_INOTIFY,
_SOURCE_EVENT_SOURCE_TYPE_MAX,
_SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
} EventSourceType;
@@ -73,6 +59,7 @@ static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX]
[SOURCE_POST] = "post",
[SOURCE_EXIT] = "exit",
[SOURCE_WATCHDOG] = "watchdog",
+ [SOURCE_INOTIFY] = "inotify",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
@@ -84,12 +71,15 @@ typedef enum WakeupType {
WAKEUP_EVENT_SOURCE,
WAKEUP_CLOCK_DATA,
WAKEUP_SIGNAL_DATA,
+ WAKEUP_INOTIFY_DATA,
_WAKEUP_TYPE_MAX,
_WAKEUP_TYPE_INVALID = -1,
} WakeupType;
#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM)
+struct inode_data;
+
struct sd_event_source {
WakeupType wakeup;
@@ -113,6 +103,8 @@ struct sd_event_source {
uint64_t pending_iteration;
uint64_t prepare_iteration;
+ sd_event_destroy_t destroy_callback;
+
LIST_FIELDS(sd_event_source, sources);
union {
@@ -151,6 +143,12 @@ struct sd_event_source {
sd_event_handler_t callback;
unsigned prioq_index;
} exit;
+ struct {
+ sd_event_inotify_handler_t callback;
+ uint32_t mask;
+ struct inode_data *inode_data;
+ LIST_FIELDS(sd_event_source, by_inode_data);
+ } inotify;
};
};
@@ -185,6 +183,64 @@ struct signal_data {
sd_event_source *current;
};
+/* A structure listing all event sources currently watching a specific inode */
+struct inode_data {
+ /* The identifier for the inode, the combination of the .st_dev + .st_ino fields of the file */
+ ino_t ino;
+ dev_t dev;
+
+ /* An fd of the inode to watch. The fd is kept open until the next iteration of the loop, so that we can
+ * rearrange the priority still until then, as we need the original inode to change the priority as we need to
+ * add a watch descriptor to the right inotify for the priority which we can only do if we have a handle to the
+ * original inode. We keep a list of all inode_data objects with an open fd in the to_close list (see below) of
+ * the sd-event object, so that it is efficient to close everything, before entering the next event loop
+ * iteration. */
+ int fd;
+
+ /* The inotify "watch descriptor" */
+ int wd;
+
+ /* The combination of the mask of all inotify watches on this inode we manage. This is also the mask that has
+ * most recently been set on the watch descriptor. */
+ uint32_t combined_mask;
+
+ /* All event sources subscribed to this inode */
+ LIST_HEAD(sd_event_source, event_sources);
+
+ /* The inotify object we watch this inode with */
+ struct inotify_data *inotify_data;
+
+ /* A linked list of all inode data objects with fds to close (see above) */
+ LIST_FIELDS(struct inode_data, to_close);
+};
+
+/* A structure encapsulating an inotify fd */
+struct inotify_data {
+ WakeupType wakeup;
+
+ /* For each priority we maintain one inotify fd, so that we only have to dequeue a single event per priority at
+ * a time */
+
+ int fd;
+ int64_t priority;
+
+ Hashmap *inodes; /* The inode_data structures keyed by dev+ino */
+ Hashmap *wd; /* The inode_data structures keyed by the watch descriptor for each */
+
+ /* The buffer we read inotify events into */
+ union inotify_event_buffer buffer;
+ size_t buffer_filled; /* fill level of the buffer */
+
+ /* How many event sources are currently marked pending for this inotify. We won't read new events off the
+ * inotify fd as long as there are still pending events on the inotify (because we have no strategy of queuing
+ * the events locally if they can't be coalesced). */
+ unsigned n_pending;
+
+ /* A linked list of all inotify objects with data already read, that still need processing. We keep this list
+ * to make it efficient to figure out what inotify objects to process data on next. */
+ LIST_FIELDS(struct inotify_data, buffered);
+};
+
struct sd_event {
unsigned n_ref;
@@ -215,6 +271,14 @@ struct sd_event {
Prioq *exit;
+ Hashmap *inotify_data; /* indexed by priority */
+
+ /* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */
+ LIST_HEAD(struct inode_data, inode_data_to_close);
+
+ /* A list of inotify objects that already have events buffered which aren't processed yet */
+ LIST_HEAD(struct inotify_data, inotify_data_buffered);
+
pid_t original_pid;
uint64_t iteration;
@@ -244,6 +308,7 @@ struct sd_event {
static thread_local sd_event *default_event = NULL;
static void source_disconnect(sd_event_source *s);
+static void event_gc_inode_data(sd_event *e, struct inode_data *d);
static sd_event *event_resolve(sd_event *e) {
return e == SD_EVENT_DEFAULT ? default_event : e;
@@ -425,6 +490,8 @@ static void event_free(sd_event *e) {
free(e->signal_sources);
hashmap_free(e->signal_data);
+ hashmap_free(e->inotify_data);
+
hashmap_free(e->child_sources);
set_free(e->post_sources);
free(e);
@@ -436,16 +503,32 @@ _public_ int sd_event_new(sd_event** ret) {
assert_return(ret, -EINVAL);
- e = new0(sd_event, 1);
+ e = new(sd_event, 1);
if (!e)
return -ENOMEM;
- e->n_ref = 1;
- e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->boottime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1;
- e->realtime.next = e->boottime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = USEC_INFINITY;
- e->realtime.wakeup = e->boottime.wakeup = e->monotonic.wakeup = e->realtime_alarm.wakeup = e->boottime_alarm.wakeup = WAKEUP_CLOCK_DATA;
- e->original_pid = getpid_cached();
- e->perturb = USEC_INFINITY;
+ *e = (sd_event) {
+ .n_ref = 1,
+ .epoll_fd = -1,
+ .watchdog_fd = -1,
+ .realtime.wakeup = WAKEUP_CLOCK_DATA,
+ .realtime.fd = -1,
+ .realtime.next = USEC_INFINITY,
+ .boottime.wakeup = WAKEUP_CLOCK_DATA,
+ .boottime.fd = -1,
+ .boottime.next = USEC_INFINITY,
+ .monotonic.wakeup = WAKEUP_CLOCK_DATA,
+ .monotonic.fd = -1,
+ .monotonic.next = USEC_INFINITY,
+ .realtime_alarm.wakeup = WAKEUP_CLOCK_DATA,
+ .realtime_alarm.fd = -1,
+ .realtime_alarm.next = USEC_INFINITY,
+ .boottime_alarm.wakeup = WAKEUP_CLOCK_DATA,
+ .boottime_alarm.fd = -1,
+ .boottime_alarm.next = USEC_INFINITY,
+ .perturb = USEC_INFINITY,
+ .original_pid = getpid_cached(),
+ };
r = prioq_ensure_allocated(&e->pending, pending_prioq_compare);
if (r < 0)
@@ -531,18 +614,17 @@ static int source_io_register(
int enabled,
uint32_t events) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
int r;
assert(s);
assert(s->type == SOURCE_IO);
assert(enabled != SD_EVENT_OFF);
- ev.events = events;
- ev.data.ptr = s;
-
- if (enabled == SD_EVENT_ONESHOT)
- ev.events |= EPOLLONESHOT;
+ ev = (struct epoll_event) {
+ .events = events | (enabled == SD_EVENT_ONESHOT ? EPOLLONESHOT : 0),
+ .data.ptr = s,
+ };
if (s->io.registered)
r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev);
@@ -634,7 +716,7 @@ static int event_make_signal_data(
int sig,
struct signal_data **ret) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
struct signal_data *d;
bool added = false;
sigset_t ss_copy;
@@ -649,7 +731,7 @@ static int event_make_signal_data(
if (e->signal_sources && e->signal_sources[sig])
priority = e->signal_sources[sig]->priority;
else
- priority = 0;
+ priority = SD_EVENT_PRIORITY_NORMAL;
d = hashmap_get(e->signal_data, &priority);
if (d) {
@@ -663,13 +745,15 @@ static int event_make_signal_data(
if (r < 0)
return r;
- d = new0(struct signal_data, 1);
+ d = new(struct signal_data, 1);
if (!d)
return -ENOMEM;
- d->wakeup = WAKEUP_SIGNAL_DATA;
- d->fd = -1;
- d->priority = priority;
+ *d = (struct signal_data) {
+ .wakeup = WAKEUP_SIGNAL_DATA,
+ .fd = -1,
+ .priority = priority,
+ };
r = hashmap_put(e->signal_data, &d->priority, d);
if (r < 0) {
@@ -699,8 +783,10 @@ static int event_make_signal_data(
d->fd = fd_move_above_stdio(r);
- ev.events = EPOLLIN;
- ev.data.ptr = d;
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev);
if (r < 0) {
@@ -867,6 +953,41 @@ static void source_disconnect(sd_event_source *s) {
prioq_remove(s->event->exit, s, &s->exit.prioq_index);
break;
+ case SOURCE_INOTIFY: {
+ struct inode_data *inode_data;
+
+ inode_data = s->inotify.inode_data;
+ if (inode_data) {
+ struct inotify_data *inotify_data;
+ assert_se(inotify_data = inode_data->inotify_data);
+
+ /* Detach this event source from the inode object */
+ LIST_REMOVE(inotify.by_inode_data, inode_data->event_sources, s);
+ s->inotify.inode_data = NULL;
+
+ if (s->pending) {
+ assert(inotify_data->n_pending > 0);
+ inotify_data->n_pending--;
+ }
+
+ /* Note that we don't reduce the inotify mask for the watch descriptor here if the inode is
+ * continued to being watched. That's because inotify doesn't really have an API for that: we
+ * can only change watch masks with access to the original inode either by fd or by path. But
+ * paths aren't stable, and keeping an O_PATH fd open all the time would mean wasting an fd
+ * continously and keeping the mount busy which we can't really do. We could reconstruct the
+ * original inode from /proc/self/fdinfo/$INOTIFY_FD (as all watch descriptors are listed
+ * there), but given the need for open_by_handle_at() which is privileged and not universally
+ * available this would be quite an incomplete solution. Hence we go the other way, leave the
+ * mask set, even if it is not minimized now, and ignore all events we aren't interested in
+ * anymore after reception. Yes, this sucks, but … Linux … */
+
+ /* Maybe release the inode data (and its inotify) */
+ event_gc_inode_data(s->event, inode_data);
+ }
+
+ break;
+ }
+
default:
assert_not_reached("Wut? I shouldn't exist.");
}
@@ -894,7 +1015,10 @@ static void source_free(sd_event_source *s) {
source_disconnect(s);
if (s->type == SOURCE_IO && s->io.owned)
- safe_close(s->io.fd);
+ s->io.fd = safe_close(s->io.fd);
+
+ if (s->destroy_callback)
+ s->destroy_callback(s->userdata);
free(s->description);
free(s);
@@ -941,6 +1065,19 @@ static int source_set_pending(sd_event_source *s, bool b) {
d->current = NULL;
}
+ if (s->type == SOURCE_INOTIFY) {
+
+ assert(s->inotify.inode_data);
+ assert(s->inotify.inode_data->inotify_data);
+
+ if (b)
+ s->inotify.inode_data->inotify_data->n_pending ++;
+ else {
+ assert(s->inotify.inode_data->inotify_data->n_pending > 0);
+ s->inotify.inode_data->inotify_data->n_pending --;
+ }
+ }
+
return 0;
}
@@ -949,15 +1086,18 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t
assert(e);
- s = new0(sd_event_source, 1);
+ s = new(sd_event_source, 1);
if (!s)
return NULL;
- s->n_ref = 1;
- s->event = e;
- s->floating = floating;
- s->type = type;
- s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
+ *s = (struct sd_event_source) {
+ .n_ref = 1,
+ .event = e,
+ .floating = floating,
+ .type = type,
+ .pending_index = PRIOQ_IDX_NULL,
+ .prepare_index = PRIOQ_IDX_NULL,
+ };
if (!floating)
sd_event_ref(e);
@@ -1034,7 +1174,7 @@ static int event_setup_timer_fd(
struct clock_data *d,
clockid_t clock) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
int r, fd;
assert(e);
@@ -1049,8 +1189,10 @@ static int event_setup_timer_fd(
fd = fd_move_above_stdio(fd);
- ev.events = EPOLLIN;
- ev.data.ptr = d;
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
if (r < 0) {
@@ -1387,6 +1529,405 @@ _public_ int sd_event_add_exit(
return 0;
}
+static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
+ assert(e);
+
+ if (!d)
+ return;
+
+ assert(hashmap_isempty(d->inodes));
+ assert(hashmap_isempty(d->wd));
+
+ if (d->buffer_filled > 0)
+ LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+
+ hashmap_free(d->inodes);
+ hashmap_free(d->wd);
+
+ assert_se(hashmap_remove(e->inotify_data, &d->priority) == d);
+
+ if (d->fd >= 0) {
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, d->fd, NULL) < 0)
+ log_debug_errno(errno, "Failed to remove inotify fd from epoll, ignoring: %m");
+
+ safe_close(d->fd);
+ }
+ free(d);
+}
+
+static int event_make_inotify_data(
+ sd_event *e,
+ int64_t priority,
+ struct inotify_data **ret) {
+
+ _cleanup_close_ int fd = -1;
+ struct inotify_data *d;
+ struct epoll_event ev;
+ int r;
+
+ assert(e);
+
+ d = hashmap_get(e->inotify_data, &priority);
+ if (d) {
+ if (ret)
+ *ret = d;
+ return 0;
+ }
+
+ fd = inotify_init1(IN_NONBLOCK|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ fd = fd_move_above_stdio(fd);
+
+ r = hashmap_ensure_allocated(&e->inotify_data, &uint64_hash_ops);
+ if (r < 0)
+ return r;
+
+ d = new(struct inotify_data, 1);
+ if (!d)
+ return -ENOMEM;
+
+ *d = (struct inotify_data) {
+ .wakeup = WAKEUP_INOTIFY_DATA,
+ .fd = TAKE_FD(fd),
+ .priority = priority,
+ };
+
+ r = hashmap_put(e->inotify_data, &d->priority, d);
+ if (r < 0) {
+ d->fd = safe_close(d->fd);
+ free(d);
+ return r;
+ }
+
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
+
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev) < 0) {
+ r = -errno;
+ d->fd = safe_close(d->fd); /* let's close this ourselves, as event_free_inotify_data() would otherwise
+ * remove the fd from the epoll first, which we don't want as we couldn't
+ * add it in the first place. */
+ event_free_inotify_data(e, d);
+ return r;
+ }
+
+ if (ret)
+ *ret = d;
+
+ return 1;
+}
+
+static int inode_data_compare(const void *a, const void *b) {
+ const struct inode_data *x = a, *y = b;
+
+ assert(x);
+ assert(y);
+
+ if (x->dev < y->dev)
+ return -1;
+ if (x->dev > y->dev)
+ return 1;
+
+ if (x->ino < y->ino)
+ return -1;
+ if (x->ino > y->ino)
+ return 1;
+
+ return 0;
+}
+
+static void inode_data_hash_func(const void *p, struct siphash *state) {
+ const struct inode_data *d = p;
+
+ assert(p);
+
+ siphash24_compress(&d->dev, sizeof(d->dev), state);
+ siphash24_compress(&d->ino, sizeof(d->ino), state);
+}
+
+const struct hash_ops inode_data_hash_ops = {
+ .hash = inode_data_hash_func,
+ .compare = inode_data_compare
+};
+
+static void event_free_inode_data(
+ sd_event *e,
+ struct inode_data *d) {
+
+ assert(e);
+
+ if (!d)
+ return;
+
+ assert(!d->event_sources);
+
+ if (d->fd >= 0) {
+ LIST_REMOVE(to_close, e->inode_data_to_close, d);
+ safe_close(d->fd);
+ }
+
+ if (d->inotify_data) {
+
+ if (d->wd >= 0) {
+ if (d->inotify_data->fd >= 0) {
+ /* So here's a problem. At the time this runs the watch descriptor might already be
+ * invalidated, because an IN_IGNORED event might be queued right the moment we enter
+ * the syscall. Hence, whenever we get EINVAL, ignore it entirely, since it's a very
+ * likely case to happen. */
+
+ if (inotify_rm_watch(d->inotify_data->fd, d->wd) < 0 && errno != EINVAL)
+ log_debug_errno(errno, "Failed to remove watch descriptor %i from inotify, ignoring: %m", d->wd);
+ }
+
+ assert_se(hashmap_remove(d->inotify_data->wd, INT_TO_PTR(d->wd)) == d);
+ }
+
+ assert_se(hashmap_remove(d->inotify_data->inodes, d) == d);
+ }
+
+ free(d);
+}
+
+static void event_gc_inode_data(
+ sd_event *e,
+ struct inode_data *d) {
+
+ struct inotify_data *inotify_data;
+
+ assert(e);
+
+ if (!d)
+ return;
+
+ if (d->event_sources)
+ return;
+
+ inotify_data = d->inotify_data;
+ event_free_inode_data(e, d);
+
+ if (inotify_data && hashmap_isempty(inotify_data->inodes))
+ event_free_inotify_data(e, inotify_data);
+}
+
+static int event_make_inode_data(
+ sd_event *e,
+ struct inotify_data *inotify_data,
+ dev_t dev,
+ ino_t ino,
+ struct inode_data **ret) {
+
+ struct inode_data *d, key;
+ int r;
+
+ assert(e);
+ assert(inotify_data);
+
+ key = (struct inode_data) {
+ .ino = ino,
+ .dev = dev,
+ };
+
+ d = hashmap_get(inotify_data->inodes, &key);
+ if (d) {
+ if (ret)
+ *ret = d;
+
+ return 0;
+ }
+
+ r = hashmap_ensure_allocated(&inotify_data->inodes, &inode_data_hash_ops);
+ if (r < 0)
+ return r;
+
+ d = new(struct inode_data, 1);
+ if (!d)
+ return -ENOMEM;
+
+ *d = (struct inode_data) {
+ .dev = dev,
+ .ino = ino,
+ .wd = -1,
+ .fd = -1,
+ .inotify_data = inotify_data,
+ };
+
+ r = hashmap_put(inotify_data->inodes, d, d);
+ if (r < 0) {
+ free(d);
+ return r;
+ }
+
+ if (ret)
+ *ret = d;
+
+ return 1;
+}
+
+static uint32_t inode_data_determine_mask(struct inode_data *d) {
+ bool excl_unlink = true;
+ uint32_t combined = 0;
+ sd_event_source *s;
+
+ assert(d);
+
+ /* Combines the watch masks of all event sources watching this inode. We generally just OR them together, but
+ * the IN_EXCL_UNLINK flag is ANDed instead.
+ *
+ * Note that we add all sources to the mask here, regardless whether enabled, disabled or oneshot. That's
+ * because we cannot change the mask anymore after the event source was created once, since the kernel has no
+ * API for that. Hence we need to subscribe to the maximum mask we ever might be interested in, and supress
+ * events we don't care for client-side. */
+
+ LIST_FOREACH(inotify.by_inode_data, s, d->event_sources) {
+
+ if ((s->inotify.mask & IN_EXCL_UNLINK) == 0)
+ excl_unlink = false;
+
+ combined |= s->inotify.mask;
+ }
+
+ return (combined & ~(IN_ONESHOT|IN_DONT_FOLLOW|IN_ONLYDIR|IN_EXCL_UNLINK)) | (excl_unlink ? IN_EXCL_UNLINK : 0);
+}
+
+static int inode_data_realize_watch(sd_event *e, struct inode_data *d) {
+ uint32_t combined_mask;
+ int wd, r;
+
+ assert(d);
+ assert(d->fd >= 0);
+
+ combined_mask = inode_data_determine_mask(d);
+
+ if (d->wd >= 0 && combined_mask == d->combined_mask)
+ return 0;
+
+ r = hashmap_ensure_allocated(&d->inotify_data->wd, NULL);
+ if (r < 0)
+ return r;
+
+ wd = inotify_add_watch_fd(d->inotify_data->fd, d->fd, combined_mask);
+ if (wd < 0)
+ return -errno;
+
+ if (d->wd < 0) {
+ r = hashmap_put(d->inotify_data->wd, INT_TO_PTR(wd), d);
+ if (r < 0) {
+ (void) inotify_rm_watch(d->inotify_data->fd, wd);
+ return r;
+ }
+
+ d->wd = wd;
+
+ } else if (d->wd != wd) {
+
+ log_debug("Weird, the watch descriptor we already knew for this inode changed?");
+ (void) inotify_rm_watch(d->fd, wd);
+ return -EINVAL;
+ }
+
+ d->combined_mask = combined_mask;
+ return 1;
+}
+
+_public_ int sd_event_add_inotify(
+ sd_event *e,
+ sd_event_source **ret,
+ const char *path,
+ uint32_t mask,
+ sd_event_inotify_handler_t callback,
+ void *userdata) {
+
+ bool rm_inotify = false, rm_inode = false;
+ struct inotify_data *inotify_data = NULL;
+ struct inode_data *inode_data = NULL;
+ _cleanup_close_ int fd = -1;
+ sd_event_source *s;
+ struct stat st;
+ int r;
+
+ assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
+ assert_return(path, -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
+ assert_return(!event_pid_changed(e), -ECHILD);
+
+ /* Refuse IN_MASK_ADD since we coalesce watches on the same inode, and hence really don't want to merge
+ * masks. Or in other words, this whole code exists only to manage IN_MASK_ADD type operations for you, hence
+ * the user can't use them for us. */
+ if (mask & IN_MASK_ADD)
+ return -EINVAL;
+
+ fd = open(path, O_PATH|O_CLOEXEC|
+ (mask & IN_ONLYDIR ? O_DIRECTORY : 0)|
+ (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0));
+ if (fd < 0)
+ return -errno;
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ s = source_new(e, !ret, SOURCE_INOTIFY);
+ if (!s)
+ return -ENOMEM;
+
+ s->enabled = mask & IN_ONESHOT ? SD_EVENT_ONESHOT : SD_EVENT_ON;
+ s->inotify.mask = mask;
+ s->inotify.callback = callback;
+ s->userdata = userdata;
+
+ /* Allocate an inotify object for this priority, and an inode object within it */
+ r = event_make_inotify_data(e, SD_EVENT_PRIORITY_NORMAL, &inotify_data);
+ if (r < 0)
+ goto fail;
+ rm_inotify = r > 0;
+
+ r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data);
+ if (r < 0)
+ goto fail;
+ rm_inode = r > 0;
+
+ /* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of
+ * the event source, until then, for which we need the original inode. */
+ if (inode_data->fd < 0) {
+ inode_data->fd = TAKE_FD(fd);
+ LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
+ }
+
+ /* Link our event source to the inode data object */
+ LIST_PREPEND(inotify.by_inode_data, inode_data->event_sources, s);
+ s->inotify.inode_data = inode_data;
+
+ rm_inode = rm_inotify = false;
+
+ /* Actually realize the watch now */
+ r = inode_data_realize_watch(e, inode_data);
+ if (r < 0)
+ goto fail;
+
+ (void) sd_event_source_set_description(s, path);
+
+ if (ret)
+ *ret = s;
+
+ return 0;
+
+fail:
+ source_free(s);
+
+ if (rm_inode)
+ event_free_inode_data(e, inode_data);
+
+ if (rm_inotify)
+ event_free_inotify_data(e, inotify_data);
+
+ return r;
+}
+
_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
if (!s)
@@ -1541,6 +2082,10 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
if (s->io.events == events && !(events & EPOLLET))
return 0;
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+
if (s->enabled != SD_EVENT_OFF) {
r = source_io_register(s, s->enabled, events);
if (r < 0)
@@ -1548,7 +2093,6 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
}
s->io.events = events;
- source_set_pending(s, false);
return 0;
}
@@ -1581,6 +2125,9 @@ _public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority)
}
_public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) {
+ bool rm_inotify = false, rm_inode = false;
+ struct inotify_data *new_inotify_data = NULL;
+ struct inode_data *new_inode_data = NULL;
int r;
assert_return(s, -EINVAL);
@@ -1590,7 +2137,59 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
if (s->priority == priority)
return 0;
- if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) {
+ if (s->type == SOURCE_INOTIFY) {
+ struct inode_data *old_inode_data;
+
+ assert(s->inotify.inode_data);
+ old_inode_data = s->inotify.inode_data;
+
+ /* We need the original fd to change the priority. If we don't have it we can't change the priority,
+ * anymore. Note that we close any fds when entering the next event loop iteration, i.e. for inotify
+ * events we allow priority changes only until the first following iteration. */
+ if (old_inode_data->fd < 0)
+ return -EOPNOTSUPP;
+
+ r = event_make_inotify_data(s->event, priority, &new_inotify_data);
+ if (r < 0)
+ return r;
+ rm_inotify = r > 0;
+
+ r = event_make_inode_data(s->event, new_inotify_data, old_inode_data->dev, old_inode_data->ino, &new_inode_data);
+ if (r < 0)
+ goto fail;
+ rm_inode = r > 0;
+
+ if (new_inode_data->fd < 0) {
+ /* Duplicate the fd for the new inode object if we don't have any yet */
+ new_inode_data->fd = fcntl(old_inode_data->fd, F_DUPFD_CLOEXEC, 3);
+ if (new_inode_data->fd < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data);
+ }
+
+ /* Move the event source to the new inode data structure */
+ LIST_REMOVE(inotify.by_inode_data, old_inode_data->event_sources, s);
+ LIST_PREPEND(inotify.by_inode_data, new_inode_data->event_sources, s);
+ s->inotify.inode_data = new_inode_data;
+
+ /* Now create the new watch */
+ r = inode_data_realize_watch(s->event, new_inode_data);
+ if (r < 0) {
+ /* Move it back */
+ LIST_REMOVE(inotify.by_inode_data, new_inode_data->event_sources, s);
+ LIST_PREPEND(inotify.by_inode_data, old_inode_data->event_sources, s);
+ s->inotify.inode_data = old_inode_data;
+ goto fail;
+ }
+
+ s->priority = priority;
+
+ event_gc_inode_data(s->event, old_inode_data);
+
+ } else if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) {
struct signal_data *old, *d;
/* Move us from the signalfd belonging to the old
@@ -1620,6 +2219,15 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
return 0;
+
+fail:
+ if (rm_inode)
+ event_free_inode_data(s->event, new_inode_data);
+
+ if (rm_inotify)
+ event_free_inotify_data(s->event, new_inotify_data);
+
+ return r;
}
_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
@@ -1648,6 +2256,13 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
if (m == SD_EVENT_OFF) {
+ /* Unset the pending flag when this event source is disabled */
+ if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+ }
+
switch (s->type) {
case SOURCE_IO:
@@ -1694,6 +2309,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
case SOURCE_DEFER:
case SOURCE_POST:
+ case SOURCE_INOTIFY:
s->enabled = m;
break;
@@ -1702,6 +2318,14 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
}
} else {
+
+ /* Unset the pending flag when this event source is enabled */
+ if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+ }
+
switch (s->type) {
case SOURCE_IO:
@@ -1766,6 +2390,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
case SOURCE_DEFER:
case SOURCE_POST:
+ case SOURCE_INOTIFY:
s->enabled = m;
break;
@@ -1795,15 +2420,18 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
+ int r;
assert_return(s, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
- s->time.next = usec;
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
- source_set_pending(s, false);
+ s->time.next = usec;
d = event_get_clock_data(s->event, s->type);
assert(d);
@@ -1827,6 +2455,7 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use
_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
+ int r;
assert_return(s, -EINVAL);
assert_return(usec != (uint64_t) -1, -EINVAL);
@@ -1834,13 +2463,15 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+
if (usec == 0)
usec = DEFAULT_ACCURACY_USEC;
s->time.accuracy = usec;
- source_set_pending(s, false);
-
d = event_get_clock_data(s->event, s->type);
assert(d);
@@ -1870,6 +2501,16 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
return 0;
}
+_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *mask) {
+ assert_return(s, -EINVAL);
+ assert_return(mask, -EINVAL);
+ assert_return(s->type == SOURCE_INOTIFY, -EDOM);
+ assert_return(!event_pid_changed(s->event), -ECHILD);
+
+ *mask = s->inotify.mask;
+ return 0;
+}
+
_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
int r;
@@ -2203,6 +2844,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
int r;
assert(e);
+ assert(d);
assert_return(events == EPOLLIN, -EIO);
/* If there's a signal queued on this priority and SIGCHLD is
@@ -2259,6 +2901,160 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
}
}
+static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents) {
+ ssize_t n;
+
+ assert(e);
+ assert(d);
+
+ assert_return(revents == EPOLLIN, -EIO);
+
+ /* If there's already an event source pending for this priority, don't read another */
+ if (d->n_pending > 0)
+ return 0;
+
+ /* Is the read buffer non-empty? If so, let's not read more */
+ if (d->buffer_filled > 0)
+ return 0;
+
+ n = read(d->fd, &d->buffer, sizeof(d->buffer));
+ if (n < 0) {
+ if (IN_SET(errno, EAGAIN, EINTR))
+ return 0;
+
+ return -errno;
+ }
+
+ assert(n > 0);
+ d->buffer_filled = (size_t) n;
+ LIST_PREPEND(buffered, e->inotify_data_buffered, d);
+
+ return 1;
+}
+
+static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t sz) {
+ assert(e);
+ assert(d);
+ assert(sz <= d->buffer_filled);
+
+ if (sz == 0)
+ return;
+
+ /* Move the rest to the buffer to the front, in order to get things properly aligned again */
+ memmove(d->buffer.raw, d->buffer.raw + sz, d->buffer_filled - sz);
+ d->buffer_filled -= sz;
+
+ if (d->buffer_filled == 0)
+ LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+}
+
+static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
+ int r;
+
+ assert(e);
+ assert(d);
+
+ /* If there's already an event source pending for this priority, don't read another */
+ if (d->n_pending > 0)
+ return 0;
+
+ while (d->buffer_filled > 0) {
+ size_t sz;
+
+ /* Let's validate that the event structures are complete */
+ if (d->buffer_filled < offsetof(struct inotify_event, name))
+ return -EIO;
+
+ sz = offsetof(struct inotify_event, name) + d->buffer.ev.len;
+ if (d->buffer_filled < sz)
+ return -EIO;
+
+ if (d->buffer.ev.mask & IN_Q_OVERFLOW) {
+ struct inode_data *inode_data;
+ Iterator i;
+
+ /* The queue overran, let's pass this event to all event sources connected to this inotify
+ * object */
+
+ HASHMAP_FOREACH(inode_data, d->inodes, i) {
+ sd_event_source *s;
+
+ LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) {
+
+ if (s->enabled == SD_EVENT_OFF)
+ continue;
+
+ r = source_set_pending(s, true);
+ if (r < 0)
+ return r;
+ }
+ }
+ } else {
+ struct inode_data *inode_data;
+ sd_event_source *s;
+
+ /* Find the inode object for this watch descriptor. If IN_IGNORED is set we also remove it from
+ * our watch descriptor table. */
+ if (d->buffer.ev.mask & IN_IGNORED) {
+
+ inode_data = hashmap_remove(d->wd, INT_TO_PTR(d->buffer.ev.wd));
+ if (!inode_data) {
+ event_inotify_data_drop(e, d, sz);
+ continue;
+ }
+
+ /* The watch descriptor was removed by the kernel, let's drop it here too */
+ inode_data->wd = -1;
+ } else {
+ inode_data = hashmap_get(d->wd, INT_TO_PTR(d->buffer.ev.wd));
+ if (!inode_data) {
+ event_inotify_data_drop(e, d, sz);
+ continue;
+ }
+ }
+
+ /* Trigger all event sources that are interested in these events. Also trigger all event
+ * sources if IN_IGNORED or IN_UNMOUNT is set. */
+ LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) {
+
+ if (s->enabled == SD_EVENT_OFF)
+ continue;
+
+ if ((d->buffer.ev.mask & (IN_IGNORED|IN_UNMOUNT)) == 0 &&
+ (s->inotify.mask & d->buffer.ev.mask & IN_ALL_EVENTS) == 0)
+ continue;
+
+ r = source_set_pending(s, true);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ /* Something pending now? If so, let's finish, otherwise let's read more. */
+ if (d->n_pending > 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int process_inotify(sd_event *e) {
+ struct inotify_data *d;
+ int r, done = 0;
+
+ assert(e);
+
+ LIST_FOREACH(buffered, d, e->inotify_data_buffered) {
+ r = event_inotify_data_process(e, d);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ done ++;
+ }
+
+ return done;
+}
+
static int source_dispatch(sd_event_source *s) {
EventSourceType saved_type;
int r = 0;
@@ -2328,7 +3124,7 @@ static int source_dispatch(sd_event_source *s) {
/* Now, reap the PID for good. */
if (zombie)
- waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
+ (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
break;
}
@@ -2345,6 +3141,28 @@ static int source_dispatch(sd_event_source *s) {
r = s->exit.callback(s, s->userdata);
break;
+ case SOURCE_INOTIFY: {
+ struct sd_event *e = s->event;
+ struct inotify_data *d;
+ size_t sz;
+
+ assert(s->inotify.inode_data);
+ assert_se(d = s->inotify.inode_data->inotify_data);
+
+ assert(d->buffer_filled >= offsetof(struct inotify_event, name));
+ sz = offsetof(struct inotify_event, name) + d->buffer.ev.len;
+ assert(d->buffer_filled >= sz);
+
+ r = s->inotify.callback(s, &d->buffer.ev, s->userdata);
+
+ /* When no event is pending anymore on this inotify object, then let's drop the event from the
+ * buffer. */
+ if (d->n_pending == 0)
+ event_inotify_data_drop(e, d, sz);
+
+ break;
+ }
+
case SOURCE_WATCHDOG:
case _SOURCE_EVENT_SOURCE_TYPE_MAX:
case _SOURCE_EVENT_SOURCE_TYPE_INVALID:
@@ -2403,6 +3221,7 @@ static int event_prepare(sd_event *e) {
static int dispatch_exit(sd_event *e) {
sd_event_source *p;
+ _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
int r;
assert(e);
@@ -2413,15 +3232,11 @@ static int dispatch_exit(sd_event *e) {
return 0;
}
- sd_event_ref(e);
+ ref = sd_event_ref(e);
e->iteration++;
e->state = SD_EVENT_EXITING;
-
r = source_dispatch(p);
-
e->state = SD_EVENT_INITIAL;
- sd_event_unref(e);
-
return r;
}
@@ -2482,6 +3297,25 @@ static int process_watchdog(sd_event *e) {
return arm_watchdog(e);
}
+static void event_close_inode_data_fds(sd_event *e) {
+ struct inode_data *d;
+
+ assert(e);
+
+ /* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin
+ * filesystems. But we can't close them right-away as we need them as long as the user still wants to make
+ * adjustments to the even source, such as changing the priority (which requires us to remove and readd a watch
+ * for the inode). Hence, let's close them when entering the first iteration after they were added, as a
+ * compromise. */
+
+ while ((d = e->inode_data_to_close)) {
+ assert(d->fd >= 0);
+ d->fd = safe_close(d->fd);
+
+ LIST_REMOVE(to_close, e->inode_data_to_close, d);
+ }
+}
+
_public_ int sd_event_prepare(sd_event *e) {
int r;
@@ -2522,6 +3356,8 @@ _public_ int sd_event_prepare(sd_event *e) {
if (r < 0)
return r;
+ event_close_inode_data_fds(e);
+
if (event_next_pending(e) || e->need_process_child)
goto pending;
@@ -2557,6 +3393,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
ev_queue_max = MAX(e->n_sources, 1u);
ev_queue = newa(struct epoll_event, ev_queue_max);
+ /* If we still have inotify data buffered, then query the other fds, but don't wait on it */
+ if (e->inotify_data_buffered)
+ timeout = 0;
+
m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max,
timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
if (m < 0) {
@@ -2594,6 +3434,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events);
break;
+ case WAKEUP_INOTIFY_DATA:
+ r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events);
+ break;
+
default:
assert_not_reached("Invalid wake-up pointer");
}
@@ -2632,6 +3476,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
goto finish;
}
+ r = process_inotify(e);
+ if (r < 0)
+ goto finish;
+
if (event_next_pending(e)) {
e->state = SD_EVENT_PENDING;
@@ -2661,14 +3509,12 @@ _public_ int sd_event_dispatch(sd_event *e) {
p = event_next_pending(e);
if (p) {
- sd_event_ref(e);
+ _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
+ ref = sd_event_ref(e);
e->state = SD_EVENT_RUNNING;
r = source_dispatch(p);
e->state = SD_EVENT_INITIAL;
-
- sd_event_unref(e);
-
return r;
}
@@ -2735,6 +3581,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
}
_public_ int sd_event_loop(sd_event *e) {
+ _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
int r;
assert_return(e, -EINVAL);
@@ -2742,19 +3589,15 @@ _public_ int sd_event_loop(sd_event *e) {
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
- sd_event_ref(e);
+ ref = sd_event_ref(e);
while (e->state != SD_EVENT_FINISHED) {
r = sd_event_run(e, (uint64_t) -1);
if (r < 0)
- goto finish;
+ return r;
}
- r = e->exit_code;
-
-finish:
- sd_event_unref(e);
- return r;
+ return e->exit_code;
}
_public_ int sd_event_get_fd(sd_event *e) {
@@ -2874,7 +3717,7 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
return e->watchdog;
if (b) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
r = sd_watchdog_enabled(false, &e->watchdog_period);
if (r <= 0)
@@ -2892,8 +3735,10 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
if (r < 0)
goto fail;
- ev.events = EPOLLIN;
- ev.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG);
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = INT_TO_PTR(SOURCE_WATCHDOG),
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev);
if (r < 0) {
@@ -2932,3 +3777,19 @@ _public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
*ret = e->iteration;
return 0;
}
+
+_public_ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback) {
+ assert_return(s, -EINVAL);
+
+ s->destroy_callback = callback;
+ return 0;
+}
+
+_public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret) {
+ assert_return(s, -EINVAL);
+
+ if (ret)
+ *ret = s->destroy_callback;
+
+ return !!s->destroy_callback;
+}
diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c
index 9873ae4a58..bde00cf719 100644
--- a/src/libsystemd/sd-event/test-event.c
+++ b/src/libsystemd/sd-event/test-event.c
@@ -1,33 +1,24 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/wait.h>
#include "sd-event.h"
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "log.h"
#include "macro.h"
+#include "parse-util.h"
+#include "process-util.h"
+#include "rm-rf.h"
#include "signal-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
#include "util.h"
-#include "process-util.h"
static int prepare_handler(sd_event_source *s, void *userdata) {
log_info("preparing %c", PTR_TO_INT(userdata));
@@ -197,7 +188,7 @@ static void test_basic(void) {
got_a = false, got_b = false, got_c = false, got_d = 0;
- /* Add a oneshot handler, trigger it, re-enable it, and trigger
+ /* Add a oneshot handler, trigger it, reenable it, and trigger
* it again. */
assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
@@ -355,6 +346,142 @@ static void test_rtqueue(void) {
sd_event_unref(e);
}
+#define CREATE_EVENTS_MAX (70000U)
+
+struct inotify_context {
+ bool delete_self_handler_called;
+ unsigned create_called[CREATE_EVENTS_MAX];
+ unsigned create_overflow;
+ unsigned n_create_events;
+};
+
+static void maybe_exit(sd_event_source *s, struct inotify_context *c) {
+ unsigned n;
+
+ assert(s);
+ assert(c);
+
+ if (!c->delete_self_handler_called)
+ return;
+
+ for (n = 0; n < 3; n++) {
+ unsigned i;
+
+ if (c->create_overflow & (1U << n))
+ continue;
+
+ for (i = 0; i < c->n_create_events; i++)
+ if (!(c->create_called[i] & (1U << n)))
+ return;
+ }
+
+ sd_event_exit(sd_event_source_get_event(s), 0);
+}
+
+static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
+ struct inotify_context *c = userdata;
+ const char *description;
+ unsigned bit, n;
+
+ assert_se(sd_event_source_get_description(s, &description) >= 0);
+ assert_se(safe_atou(description, &n) >= 0);
+
+ assert_se(n <= 3);
+ bit = 1U << n;
+
+ if (ev->mask & IN_Q_OVERFLOW) {
+ log_info("inotify-handler <%s>: overflow", description);
+ c->create_overflow |= bit;
+ } else if (ev->mask & IN_CREATE) {
+ unsigned i;
+
+ log_info("inotify-handler <%s>: create on %s", description, ev->name);
+
+ if (!streq(ev->name, "sub")) {
+ assert_se(safe_atou(ev->name, &i) >= 0);
+
+ assert_se(i < c->n_create_events);
+ c->create_called[i] |= bit;
+ }
+ } else if (ev->mask & IN_DELETE) {
+ log_info("inotify-handler <%s>: delete of %s", description, ev->name);
+ assert_se(streq(ev->name, "sub"));
+ } else
+ assert_not_reached("unexpected inotify event");
+
+ maybe_exit(s, c);
+ return 1;
+}
+
+static int delete_self_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
+ struct inotify_context *c = userdata;
+
+ if (ev->mask & IN_Q_OVERFLOW) {
+ log_info("delete-self-handler: overflow");
+ c->delete_self_handler_called = true;
+ } else if (ev->mask & IN_DELETE_SELF) {
+ log_info("delete-self-handler: delete-self");
+ c->delete_self_handler_called = true;
+ } else if (ev->mask & IN_IGNORED) {
+ log_info("delete-self-handler: ignore");
+ } else
+ assert_not_reached("unexpected inotify event (delete-self)");
+
+ maybe_exit(s, c);
+ return 1;
+}
+
+static void test_inotify(unsigned n_create_events) {
+ _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
+ sd_event_source *a = NULL, *b = NULL, *c = NULL, *d = NULL;
+ struct inotify_context context = {
+ .n_create_events = n_create_events,
+ };
+ sd_event *e = NULL;
+ const char *q;
+ unsigned i;
+
+ assert_se(sd_event_default(&e) >= 0);
+
+ assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
+
+ assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0);
+ assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0);
+ assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE) >= 0);
+ assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL) >= 0);
+ assert_se(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context) >= 0);
+ assert_se(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE) >= 0);
+
+ assert_se(sd_event_source_set_description(a, "0") >= 0);
+ assert_se(sd_event_source_set_description(b, "1") >= 0);
+ assert_se(sd_event_source_set_description(c, "2") >= 0);
+
+ q = strjoina(p, "/sub");
+ assert_se(touch(q) >= 0);
+ assert_se(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context) >= 0);
+
+ for (i = 0; i < n_create_events; i++) {
+ char buf[DECIMAL_STR_MAX(unsigned)+1];
+ _cleanup_free_ char *z;
+
+ xsprintf(buf, "%u", i);
+ assert_se(z = strjoin(p, "/", buf));
+
+ assert_se(touch(z) >= 0);
+ }
+
+ assert_se(unlink(q) >= 0);
+
+ assert_se(sd_event_loop(e) >= 0);
+
+ sd_event_source_unref(a);
+ sd_event_source_unref(b);
+ sd_event_source_unref(c);
+ sd_event_source_unref(d);
+
+ sd_event_unref(e);
+}
+
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
@@ -364,5 +491,8 @@ int main(int argc, char *argv[]) {
test_sd_event_now();
test_rtqueue();
+ test_inotify(100); /* should work without overflow */
+ test_inotify(33000); /* should trigger a q overflow */
+
return 0;
}
diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h
index 36dae8c755..1fc6d31aed 100644
--- a/src/libsystemd/sd-hwdb/hwdb-internal.h
+++ b/src/libsystemd/sd-hwdb/hwdb-internal.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sparse-endian.h"
#include "util.h"
diff --git a/src/libsystemd/sd-hwdb/hwdb-util.h b/src/libsystemd/sd-hwdb/hwdb-util.h
index b3053524e7..2998249199 100644
--- a/src/libsystemd/sd-hwdb/hwdb-util.h
+++ b/src/libsystemd/sd-hwdb/hwdb-util.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-hwdb.h"
diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c
index 9418e8cf38..5c612d9a2f 100644
--- a/src/libsystemd/sd-hwdb/sd-hwdb.c
+++ b/src/libsystemd/sd-hwdb/sd-hwdb.c
@@ -1,23 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
- Copyright 2008 Alan Jenkins <alan.christopher.jenkins@googlemail.com>
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2008 Alan Jenkins <alan.christopher.jenkins@googlemail.com>
***/
#include <errno.h>
@@ -373,8 +356,7 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) {
log_debug("strings %8"PRIu64" bytes", le64toh(hwdb->head->strings_len));
log_debug("nodes %8"PRIu64" bytes", le64toh(hwdb->head->nodes_len));
- *ret = hwdb;
- hwdb = NULL;
+ *ret = TAKE_PTR(hwdb);
return 0;
}
diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c
index 8ce012e35f..edee985e44 100644
--- a/src/libsystemd/sd-id128/id128-util.c
+++ b/src/libsystemd/sd-id128/id128-util.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h
index 9f3340e581..f0b4eca581 100644
--- a/src/libsystemd/sd-id128/id128-util.h
+++ b/src/libsystemd/sd-id128/id128-util.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c
index 561bcdf4f1..b7123280f3 100644
--- a/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libsystemd/sd-id128/sd-id128.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
@@ -111,7 +95,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
return r;
if (sd_id128_is_null(saved_machine_id))
- return -EINVAL;
+ return -ENOMEDIUM;
}
*ret = saved_machine_id;
diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
index 6601bcd6be..c2f7133e42 100644
--- a/src/libsystemd/sd-login/sd-login.c
+++ b/src/libsystemd/sd-login/sd-login.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
@@ -286,7 +270,7 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "STATE", &s, NULL);
if (r == -ENOENT) {
free(s);
s = strdup("offline");
@@ -317,7 +301,7 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "DISPLAY", &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -325,8 +309,7 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
if (isempty(s))
return -ENODATA;
- *session = s;
- s = NULL;
+ *session = TAKE_PTR(s);
return 0;
}
@@ -355,8 +338,7 @@ static int file_of_seat(const char *seat, char **_p) {
if (!p)
return -ENOMEM;
- *_p = p;
- p = NULL;
+ *_p = TAKE_PTR(p);
return 0;
}
@@ -374,7 +356,7 @@ _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat)
variable = require_active ? "ACTIVE_UID" : "UIDS";
- r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, variable, &s, NULL);
if (r == -ENOENT)
return 0;
if (r < 0)
@@ -403,7 +385,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, variable, &s, NULL);
if (r == -ENOENT || (r >= 0 && isempty(s))) {
if (array)
*array = NULL;
@@ -417,7 +399,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) {
return -ENOMEM;
strv_uniq(a);
- r = strv_length(a);
+ r = (int) strv_length(a);
if (array)
*array = a;
@@ -481,7 +463,7 @@ _public_ int sd_session_is_active(const char *session) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "ACTIVE", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -500,7 +482,7 @@ _public_ int sd_session_is_remote(const char *session) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "REMOTE", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -521,7 +503,7 @@ _public_ int sd_session_get_state(const char *session, char **state) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "STATE", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -529,8 +511,7 @@ _public_ int sd_session_get_state(const char *session, char **state) {
if (isempty(s))
return -EIO;
- *state = s;
- s = NULL;
+ *state = TAKE_PTR(s);
return 0;
}
@@ -545,7 +526,7 @@ _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "UID", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -567,7 +548,7 @@ static int session_get_string(const char *session, const char *field, char **val
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, field, &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, field, &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -575,8 +556,7 @@ static int session_get_string(const char *session, const char *field, char **val
if (isempty(s))
return -ENODATA;
- *value = s;
- s = NULL;
+ *value = TAKE_PTR(s);
return 0;
}
@@ -660,7 +640,7 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE,
+ r = parse_env_file(NULL, p, NEWLINE,
"ACTIVE", &s,
"ACTIVE_UID", &t,
NULL);
@@ -681,10 +661,8 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
return r;
}
- if (session && s) {
- *session = s;
- s = NULL;
- }
+ if (session && s)
+ *session = TAKE_PTR(s);
return 0;
}
@@ -700,7 +678,7 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE,
+ r = parse_env_file(NULL, p, NEWLINE,
"SESSIONS", &s,
"UIDS", &t,
NULL);
@@ -745,17 +723,13 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
}
}
- r = strv_length(a);
+ r = (int) strv_length(a);
- if (sessions) {
- *sessions = a;
- a = NULL;
- }
+ if (sessions)
+ *sessions = TAKE_PTR(a);
- if (uids) {
- *uids = b;
- b = NULL;
- }
+ if (uids)
+ *uids = TAKE_PTR(b);
if (n_uids)
*n_uids = n;
@@ -773,7 +747,7 @@ static int seat_get_can(const char *seat, const char *variable) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE,
+ r = parse_env_file(NULL, p, NEWLINE,
variable, &s,
NULL);
if (r == -ENOENT)
@@ -870,10 +844,8 @@ _public_ int sd_get_uids(uid_t **users) {
r++;
}
- if (users) {
- *users = l;
- l = NULL;
- }
+ if (users)
+ *users = TAKE_PTR(l);
return r;
}
@@ -909,10 +881,9 @@ _public_ int sd_get_machine_names(char ***machines) {
*b = NULL;
}
- if (machines) {
- *machines = l;
- l = NULL;
- }
+ if (machines)
+ *machines = TAKE_PTR(l);
+
return r;
}
@@ -925,7 +896,7 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
assert_return(class, -EINVAL);
p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "CLASS", &c, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -933,8 +904,7 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
if (!c)
return -EIO;
- *class = c;
- c = NULL;
+ *class = TAKE_PTR(c);
return 0;
}
@@ -950,7 +920,7 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
assert_return(ifindices, -EINVAL);
p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "NETIF", &netif, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c
index 559529ecf6..ccb1905a46 100644
--- a/src/libsystemd/sd-login/test-login.c
+++ b/src/libsystemd/sd-login/test-login.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <poll.h>
diff --git a/src/libsystemd/sd-netlink/generic-netlink.c b/src/libsystemd/sd-netlink/generic-netlink.c
index 771658d9ae..347bf4cbd5 100644
--- a/src/libsystemd/sd-netlink/generic-netlink.c
+++ b/src/libsystemd/sd-netlink/generic-netlink.c
@@ -58,8 +58,7 @@ static int genl_message_new(sd_netlink *nl, sd_genl_family family, uint16_t nlms
genl->cmd = cmd;
genl->version = genl_families[family].version;
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
diff --git a/src/libsystemd/sd-netlink/local-addresses.c b/src/libsystemd/sd-netlink/local-addresses.c
index 81e55b6d9f..5467ba432f 100644
--- a/src/libsystemd/sd-netlink/local-addresses.c
+++ b/src/libsystemd/sd-netlink/local-addresses.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2011 Lennart Poettering
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-netlink.h"
@@ -158,8 +139,7 @@ int local_addresses(sd_netlink *context, int ifindex, int af, struct local_addre
qsort_safe(list, n_list, sizeof(struct local_address), address_compare);
- *ret = list;
- list = NULL;
+ *ret = TAKE_PTR(list);
return (int) n_list;
}
@@ -271,8 +251,7 @@ int local_gateways(sd_netlink *context, int ifindex, int af, struct local_addres
if (n_list > 0)
qsort(list, n_list, sizeof(struct local_address), address_compare);
- *ret = list;
- list = NULL;
+ *ret = TAKE_PTR(list);
return (int) n_list;
}
diff --git a/src/libsystemd/sd-netlink/local-addresses.h b/src/libsystemd/sd-netlink/local-addresses.h
index f722242821..4fc3477e47 100644
--- a/src/libsystemd/sd-netlink/local-addresses.h
+++ b/src/libsystemd/sd-netlink/local-addresses.h
@@ -2,25 +2,8 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2008-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 "sd-netlink.h"
#include "in-addr-util.h"
diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h
index dc553d708c..dd4fa9d2af 100644
--- a/src/libsystemd/sd-netlink/netlink-internal.h
+++ b/src/libsystemd/sd-netlink/netlink-internal.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/netlink.h>
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index af3d13edcd..23907c8224 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/in.h>
#include <stdbool.h>
@@ -98,8 +80,7 @@ int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
m->hdr->nlmsg_len = size;
m->hdr->nlmsg_type = type;
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
@@ -312,7 +293,6 @@ int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uin
return 0;
}
-
int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data) {
int r;
@@ -803,8 +783,7 @@ static int netlink_container_parse(sd_netlink_message *m,
attributes[type].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER;
}
- container->attributes = attributes;
- attributes = NULL;
+ container->attributes = TAKE_PTR(attributes);
container->n_attributes = count;
return 0;
diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c
index 3474ad9ddb..f103cbedea 100644
--- a/src/libsystemd/sd-netlink/netlink-socket.c
+++ b/src/libsystemd/sd-netlink/netlink-socket.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/in.h>
#include <stdbool.h>
@@ -433,8 +415,7 @@ int socket_read_message(sd_netlink *rtnl) {
/* push the message onto the multi-part message stack */
if (first)
m->next = first;
- first = m;
- m = NULL;
+ first = TAKE_PTR(m);
}
if (len > 0)
@@ -449,8 +430,7 @@ int socket_read_message(sd_netlink *rtnl) {
if (r < 0)
return r;
- rtnl->rqueue[rtnl->rqueue_size++] = first;
- first = NULL;
+ rtnl->rqueue[rtnl->rqueue_size++] = TAKE_PTR(first);
if (multi_part && (i < rtnl->rqueue_partial_size)) {
/* remove the message form the partial read queue */
@@ -464,15 +444,14 @@ int socket_read_message(sd_netlink *rtnl) {
/* we only got a partial multi-part message, push it on the
partial read queue */
if (i < rtnl->rqueue_partial_size)
- rtnl->rqueue_partial[i] = first;
+ rtnl->rqueue_partial[i] = TAKE_PTR(first);
else {
r = rtnl_rqueue_partial_make_room(rtnl);
if (r < 0)
return r;
- rtnl->rqueue_partial[rtnl->rqueue_partial_size++] = first;
+ rtnl->rqueue_partial[rtnl->rqueue_partial_size++] = TAKE_PTR(first);
}
- first = NULL;
return 0;
}
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 0ee7d6f0dc..c93fe9cb4c 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/in.h>
#include <stdint.h>
@@ -313,6 +295,11 @@ static const NLType rtnl_link_info_data_geneve_types[] = {
[IFLA_GENEVE_LABEL] = { .type = NETLINK_TYPE_U32 },
};
+static const NLType rtnl_link_info_data_can_types[] = {
+ [IFLA_CAN_BITTIMING] = { .size = sizeof(struct can_bittiming) },
+ [IFLA_CAN_RESTART_MS] = { .type = NETLINK_TYPE_U32 },
+};
+
/* these strings must match the .kind entries in the kernel */
static const char* const nl_union_link_info_data_table[] = {
[NL_UNION_LINK_INFO_DATA_BOND] = "bond",
@@ -338,6 +325,8 @@ static const char* const nl_union_link_info_data_table[] = {
[NL_UNION_LINK_INFO_DATA_GENEVE] = "geneve",
[NL_UNION_LINK_INFO_DATA_VXCAN] = "vxcan",
[NL_UNION_LINK_INFO_DATA_WIREGUARD] = "wireguard",
+ [NL_UNION_LINK_INFO_DATA_NETDEVSIM] = "netdevsim",
+ [NL_UNION_LINK_INFO_DATA_CAN] = "can",
};
DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
@@ -383,6 +372,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
.types = rtnl_link_info_data_geneve_types },
[NL_UNION_LINK_INFO_DATA_VXCAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxcan_types),
.types = rtnl_link_info_data_vxcan_types },
+ [NL_UNION_LINK_INFO_DATA_CAN] = { .count = ELEMENTSOF(rtnl_link_info_data_can_types),
+ .types = rtnl_link_info_data_can_types },
};
static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
@@ -582,7 +573,11 @@ static const NLType rtnl_route_types[] = {
RTA_NEWDST,
*/
[RTA_PREF] = { .type = NETLINK_TYPE_U8 },
-
+/*
+ RTA_ENCAP_TYPE,
+ RTA_ENCAP,
+ */
+ [RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
};
static const NLTypeSystem rtnl_route_type_system = {
diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h
index ea7f8d5e6c..d411ffa6c2 100644
--- a/src/libsystemd/sd-netlink/netlink-types.h
+++ b/src/libsystemd/sd-netlink/netlink-types.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "macro.h"
@@ -95,6 +77,8 @@ typedef enum NLUnionLinkInfoData {
NL_UNION_LINK_INFO_DATA_GENEVE,
NL_UNION_LINK_INFO_DATA_VXCAN,
NL_UNION_LINK_INFO_DATA_WIREGUARD,
+ NL_UNION_LINK_INFO_DATA_NETDEVSIM,
+ NL_UNION_LINK_INFO_DATA_CAN,
_NL_UNION_LINK_INFO_DATA_MAX,
_NL_UNION_LINK_INFO_DATA_INVALID = -1
} NLUnionLinkInfoData;
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c
index 7680b30e70..3928dfbabf 100644
--- a/src/libsystemd/sd-netlink/netlink-util.c
+++ b/src/libsystemd/sd-netlink/netlink-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-netlink.h"
@@ -53,7 +35,7 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
}
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
- const struct ether_addr *mac, unsigned mtu) {
+ const struct ether_addr *mac, uint32_t mtu) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r;
@@ -85,7 +67,7 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
return r;
}
- if (mtu > 0) {
+ if (mtu != 0) {
r = sd_netlink_message_append_u32(message, IFLA_MTU, mtu);
if (r < 0)
return r;
diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h
index 795e4dc15c..7c35a2cfa7 100644
--- a/src/libsystemd/sd-netlink/netlink-util.h
+++ b/src/libsystemd/sd-netlink/netlink-util.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-netlink.h"
@@ -53,7 +35,7 @@ static inline bool rtnl_message_type_is_routing_policy_rule(uint16_t type) {
}
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
-int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu);
+int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu);
int rtnl_log_parse_error(int r);
int rtnl_log_create_error(int r);
diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c
index 24345c4298..4416e1720c 100644
--- a/src/libsystemd/sd-netlink/rtnl-message.c
+++ b/src/libsystemd/sd-netlink/rtnl-message.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/in.h>
#include <linux/if_addrlabel.h>
diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c
index 116e287bb6..a177f220ab 100644
--- a/src/libsystemd/sd-netlink/sd-netlink.c
+++ b/src/libsystemd/sd-netlink/sd-netlink.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <poll.h>
#include <sys/socket.h>
@@ -62,8 +44,7 @@ static int sd_netlink_new(sd_netlink **ret) {
* responses with notifications from the kernel */
rtnl->serial = 1;
- *ret = rtnl;
- rtnl = NULL;
+ *ret = TAKE_PTR(rtnl);
return 0;
}
@@ -90,8 +71,7 @@ int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) {
rtnl->fd = fd;
- *ret = rtnl;
- rtnl = NULL;
+ *ret = TAKE_PTR(rtnl);
return 0;
}
@@ -133,8 +113,7 @@ int sd_netlink_open_fd(sd_netlink **ret, int fd) {
return r;
}
- *ret = rtnl;
- rtnl = NULL;
+ *ret = TAKE_PTR(rtnl);
return 0;
}
@@ -425,8 +404,7 @@ static int process_running(sd_netlink *rtnl, sd_netlink_message **ret) {
}
if (ret) {
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 1;
}
@@ -669,10 +647,8 @@ int sd_netlink_call(sd_netlink *rtnl,
return 0;
}
- if (ret) {
- *ret = incoming;
- incoming = NULL;
- }
+ if (ret)
+ *ret = TAKE_PTR(incoming);
return 1;
}
diff --git a/src/libsystemd/sd-netlink/test-local-addresses.c b/src/libsystemd/sd-netlink/test-local-addresses.c
index bf11042221..921ce289d4 100644
--- a/src/libsystemd/sd-netlink/test-local-addresses.c
+++ b/src/libsystemd/sd-netlink/test-local-addresses.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "af-list.h"
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index 9ccc8ea607..03773fb936 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
#include <netinet/ether.h>
@@ -53,7 +35,7 @@ static void test_link_configure(sd_netlink *rtnl, int ifindex) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
const char *mac = "98:fe:94:3f:c6:18", *name = "test";
char buffer[ETHER_ADDR_TO_STRING_MAX];
- unsigned int mtu = 1450, mtu_out;
+ uint32_t mtu = 1450, mtu_out;
const char *name_out;
struct ether_addr mac_out;
@@ -79,7 +61,7 @@ static void test_link_configure(sd_netlink *rtnl, int ifindex) {
static void test_link_get(sd_netlink *rtnl, int ifindex) {
sd_netlink_message *m;
sd_netlink_message *r;
- unsigned int mtu = 1500;
+ uint32_t mtu = 1500;
const char *str_data;
uint8_t u8_data;
uint32_t u32_data;
@@ -120,7 +102,6 @@ static void test_link_get(sd_netlink *rtnl, int ifindex) {
assert_se((r = sd_netlink_message_unref(r)) == NULL);
}
-
static void test_address_get(sd_netlink *rtnl, int ifindex) {
sd_netlink_message *m;
sd_netlink_message *r;
diff --git a/src/libsystemd/sd-network/network-util.c b/src/libsystemd/sd-network/network-util.c
index 0957d593e0..256d4a27a5 100644
--- a/src/libsystemd/sd-network/network-util.c
+++ b/src/libsystemd/sd-network/network-util.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "alloc-util.h"
diff --git a/src/libsystemd/sd-network/network-util.h b/src/libsystemd/sd-network/network-util.h
index 9c6b3fc0f0..62260d09dd 100644
--- a/src/libsystemd/sd-network/network-util.h
+++ b/src/libsystemd/sd-network/network-util.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Thomas Hindø Paabøl Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-network.h"
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index 8f4814019e..3b8ce935b0 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <poll.h>
@@ -43,7 +24,7 @@ _public_ int sd_network_get_operational_state(char **state) {
assert_return(state, -EINVAL);
- r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL);
+ r = parse_env_file(NULL, "/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -51,8 +32,7 @@ _public_ int sd_network_get_operational_state(char **state) {
if (isempty(s))
return -ENODATA;
- *state = s;
- s = NULL;
+ *state = TAKE_PTR(s);
return 0;
}
@@ -64,7 +44,7 @@ static int network_get_strv(const char *key, char ***ret) {
assert_return(ret, -EINVAL);
- r = parse_env_file("/run/systemd/netif/state", NEWLINE, key, &s, NULL);
+ r = parse_env_file(NULL, "/run/systemd/netif/state", NEWLINE, key, &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -79,10 +59,9 @@ static int network_get_strv(const char *key, char ***ret) {
return -ENOMEM;
strv_uniq(a);
- r = strv_length(a);
+ r = (int) strv_length(a);
- *ret = a;
- a = NULL;
+ *ret = TAKE_PTR(a);
return r;
}
@@ -113,7 +92,7 @@ static int network_link_get_string(int ifindex, const char *field, char **ret) {
xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
- r = parse_env_file(path, NEWLINE, field, &s, NULL);
+ r = parse_env_file(NULL, path, NEWLINE, field, &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -121,8 +100,7 @@ static int network_link_get_string(int ifindex, const char *field, char **ret) {
if (isempty(s))
return -ENODATA;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
@@ -137,7 +115,7 @@ static int network_link_get_strv(int ifindex, const char *key, char ***ret) {
assert_return(ret, -EINVAL);
xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
- r = parse_env_file(path, NEWLINE, key, &s, NULL);
+ r = parse_env_file(NULL, path, NEWLINE, key, &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -152,10 +130,9 @@ static int network_link_get_strv(int ifindex, const char *key, char ***ret) {
return -ENOMEM;
strv_uniq(a);
- r = strv_length(a);
+ r = (int) strv_length(a);
- *ret = a;
- a = NULL;
+ *ret = TAKE_PTR(a);
return r;
}
@@ -195,6 +172,10 @@ _public_ int sd_network_link_get_mdns(int ifindex, char **mdns) {
return network_link_get_string(ifindex, "MDNS", mdns);
}
+_public_ int sd_network_link_get_dns_over_tls(int ifindex, char **dns_over_tls) {
+ return network_link_get_string(ifindex, "DNS_OVER_TLS", dns_over_tls);
+}
+
_public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) {
return network_link_get_string(ifindex, "DNSSEC", dnssec);
}
@@ -235,7 +216,7 @@ static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) {
assert_return(ret, -EINVAL);
xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
- r = parse_env_file(path, NEWLINE, key, &s, NULL);
+ r = parse_env_file(NULL, path, NEWLINE, key, &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -263,8 +244,7 @@ static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) {
if (ifis)
ifis[c] = 0; /* Let's add a 0 ifindex to the end, to be nice */
- *ret = ifis;
- ifis = NULL;
+ *ret = TAKE_PTR(ifis);
return c;
}
diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c
index 419c763668..2845f91e1b 100644
--- a/src/libsystemd/sd-path/sd-path.c
+++ b/src/libsystemd/sd-path/sd-path.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-path.h"
@@ -348,6 +332,7 @@ _public_ int sd_path_home(uint64_t type, const char *suffix, char **path) {
if (IN_SET(type,
SD_PATH_SEARCH_BINARIES,
+ SD_PATH_SEARCH_BINARIES_DEFAULT,
SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED,
@@ -566,19 +551,31 @@ static int get_search(uint64_t type, char ***list) {
false,
"/etc",
NULL);
- }
+
+ case SD_PATH_SEARCH_BINARIES_DEFAULT: {
+ char **t;
+
+ t = strv_split_nulstr(DEFAULT_PATH_NULSTR);
+ if (!t)
+ return -ENOMEM;
+
+ *list = t;
+ return 0;
+ }}
return -EOPNOTSUPP;
}
_public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
- char **l, **i, **j, **n;
+ char **i, **j;
+ _cleanup_strv_free_ char **l = NULL, **n = NULL;
int r;
assert_return(paths, -EINVAL);
if (!IN_SET(type,
SD_PATH_SEARCH_BINARIES,
+ SD_PATH_SEARCH_BINARIES_DEFAULT,
SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED,
@@ -601,7 +598,7 @@ _public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
l[0] = p;
l[1] = NULL;
- *paths = l;
+ *paths = TAKE_PTR(l);
return 0;
}
@@ -610,15 +607,13 @@ _public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
return r;
if (!suffix) {
- *paths = l;
+ *paths = TAKE_PTR(l);
return 0;
}
n = new(char*, strv_length(l)+1);
- if (!n) {
- strv_free(l);
+ if (!n)
return -ENOMEM;
- }
j = n;
STRV_FOREACH(i, l) {
@@ -628,16 +623,13 @@ _public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
else
*j = strjoin(*i, "/", suffix);
- if (!*j) {
- strv_free(l);
- strv_free(n);
+ if (!*j)
return -ENOMEM;
- }
j++;
}
*j = NULL;
- *paths = n;
+ *paths = TAKE_PTR(n);
return 0;
}
diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c
index 1c68a96fec..a189f140f8 100644
--- a/src/libsystemd/sd-resolve/sd-resolve.c
+++ b/src/libsystemd/sd-resolve/sd-resolve.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2005-2008 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
@@ -181,8 +165,15 @@ static void resolve_query_disconnect(sd_resolve_query *q);
#define RESOLVE_DONT_DESTROY(resolve) \
_cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
-static int send_died(int out_fd) {
+static void query_assign_errno(sd_resolve_query *q, int ret, int error, int h_error) {
+ assert(q);
+ q->ret = ret;
+ q->_errno = abs(error);
+ q->_h_errno = h_error;
+}
+
+static int send_died(int out_fd) {
RHeader rh = {
.type = RESPONSE_DIED,
.length = sizeof(RHeader),
@@ -244,12 +235,12 @@ static int send_addrinfo_reply(
._h_errno = _h_errno,
};
- struct msghdr mh = {};
- struct iovec iov[2];
union {
AddrInfoSerialization ais;
uint8_t space[BUFSIZE];
} buffer;
+ struct iovec iov[2];
+ struct msghdr mh;
assert(out_fd >= 0);
@@ -272,8 +263,7 @@ static int send_addrinfo_reply(
iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(AddrInfoResponse) };
iov[1] = (struct iovec) { .iov_base = &buffer, .iov_len = resp.header.length - sizeof(AddrInfoResponse) };
- mh.msg_iov = iov;
- mh.msg_iovlen = ELEMENTSOF(iov);
+ mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov) };
if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
return -errno;
@@ -298,8 +288,8 @@ static int send_nameinfo_reply(
._h_errno = _h_errno,
};
- struct msghdr mh = {};
struct iovec iov[3];
+ struct msghdr mh;
size_t hl, sl;
assert(out_fd >= 0);
@@ -315,8 +305,7 @@ static int send_nameinfo_reply(
iov[1] = (struct iovec) { .iov_base = (void*) host, .iov_len = hl };
iov[2] = (struct iovec) { .iov_base = (void*) serv, .iov_len = sl };
- mh.msg_iov = iov;
- mh.msg_iovlen = ELEMENTSOF(iov);
+ mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov) };
if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
return -errno;
@@ -332,32 +321,33 @@ static int handle_request(int out_fd, const Packet *packet, size_t length) {
req = &packet->rheader;
- assert(length >= sizeof(RHeader));
- assert(length == req->length);
+ assert_return(length >= sizeof(RHeader), -EIO);
+ assert_return(length == req->length, -EIO);
switch (req->type) {
case REQUEST_ADDRINFO: {
const AddrInfoRequest *ai_req = &packet->addrinfo_request;
- struct addrinfo hints = {}, *result = NULL;
+ struct addrinfo hints, *result = NULL;
const char *node, *service;
int ret;
- assert(length >= sizeof(AddrInfoRequest));
- assert(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len);
+ assert_return(length >= sizeof(AddrInfoRequest), -EBADMSG);
+ assert_return(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len, -EBADMSG);
- hints.ai_flags = ai_req->ai_flags;
- hints.ai_family = ai_req->ai_family;
- hints.ai_socktype = ai_req->ai_socktype;
- hints.ai_protocol = ai_req->ai_protocol;
+ hints = (struct addrinfo) {
+ .ai_flags = ai_req->ai_flags,
+ .ai_family = ai_req->ai_family,
+ .ai_socktype = ai_req->ai_socktype,
+ .ai_protocol = ai_req->ai_protocol,
+ };
node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
- ret = getaddrinfo(
- node, service,
- ai_req->hints_valid ? &hints : NULL,
- &result);
+ ret = getaddrinfo(node, service,
+ ai_req->hints_valid ? &hints : NULL,
+ &result);
/* send_addrinfo_reply() frees result */
return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
@@ -369,21 +359,21 @@ static int handle_request(int out_fd, const Packet *packet, size_t length) {
union sockaddr_union sa;
int ret;
- assert(length >= sizeof(NameInfoRequest));
- assert(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len);
- assert(sizeof(sa) >= ni_req->sockaddr_len);
+ assert_return(length >= sizeof(NameInfoRequest), -EBADMSG);
+ assert_return(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len, -EBADMSG);
+ assert_return(ni_req->sockaddr_len <= sizeof(sa), -EBADMSG);
memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
ret = getnameinfo(&sa.sa, ni_req->sockaddr_len,
- ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
- ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
- ni_req->flags);
+ ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
+ ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
+ ni_req->flags);
return send_nameinfo_reply(out_fd, req->id, ret,
- ret == 0 && ni_req->gethost ? hostbuf : NULL,
- ret == 0 && ni_req->getserv ? servbuf : NULL,
- errno, h_errno);
+ ret == 0 && ni_req->gethost ? hostbuf : NULL,
+ ret == 0 && ni_req->getserv ? servbuf : NULL,
+ errno, h_errno);
}
case REQUEST_TERMINATE:
@@ -410,7 +400,7 @@ static void* thread_worker(void *p) {
} buf;
ssize_t length;
- length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof(buf), 0);
+ length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof buf, 0);
if (length < 0) {
if (errno == EINTR)
continue;
@@ -420,9 +410,6 @@ static void* thread_worker(void *p) {
if (length == 0)
break;
- if (resolve->dead)
- break;
-
if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0)
break;
}
@@ -450,7 +437,6 @@ static int start_threads(sd_resolve *resolve, unsigned extra) {
n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
while (resolve->n_valid_workers < n) {
-
r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
if (r > 0) {
r = -r;
@@ -480,8 +466,8 @@ static bool resolve_pid_changed(sd_resolve *r) {
}
_public_ int sd_resolve_new(sd_resolve **ret) {
- sd_resolve *resolve = NULL;
- int i, r;
+ _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL;
+ int i;
assert_return(ret, -EINVAL);
@@ -495,17 +481,11 @@ _public_ int sd_resolve_new(sd_resolve **ret) {
for (i = 0; i < _FD_MAX; i++)
resolve->fds[i] = -1;
- r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD) < 0)
+ return -errno;
- r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD) < 0)
+ return -errno;
for (i = 0; i < _FD_MAX; i++)
resolve->fds[i] = fd_move_above_stdio(resolve->fds[i]);
@@ -517,12 +497,8 @@ _public_ int sd_resolve_new(sd_resolve **ret) {
(void) fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
- *ret = resolve;
+ *ret = TAKE_PTR(resolve);
return 0;
-
-fail:
- sd_resolve_unref(resolve);
- return r;
}
_public_ int sd_resolve_default(sd_resolve **ret) {
@@ -591,7 +567,7 @@ static void resolve_free(sd_resolve *resolve) {
RHeader req = {
.type = REQUEST_TERMINATE,
- .length = sizeof(req)
+ .length = sizeof req,
};
/* Send one termination packet for each worker */
@@ -619,7 +595,6 @@ _public_ sd_resolve* sd_resolve_ref(sd_resolve *resolve) {
}
_public_ sd_resolve* sd_resolve_unref(sd_resolve *resolve) {
-
if (!resolve)
return NULL;
@@ -765,11 +740,11 @@ static int handle_response(sd_resolve *resolve, const Packet *packet, size_t len
int r;
assert(resolve);
+ assert(packet);
resp = &packet->rheader;
- assert(resp);
- assert(length >= sizeof(RHeader));
- assert(length == resp->length);
+ assert_return(length >= sizeof(RHeader), -EIO);
+ assert_return(length == resp->length, -EIO);
if (resp->type == RESPONSE_DIED) {
resolve->dead = true;
@@ -791,12 +766,10 @@ static int handle_response(sd_resolve *resolve, const Packet *packet, size_t len
size_t l;
struct addrinfo *prev = NULL;
- assert(length >= sizeof(AddrInfoResponse));
- assert(q->type == REQUEST_ADDRINFO);
+ assert_return(length >= sizeof(AddrInfoResponse), -EBADMSG);
+ assert_return(q->type == REQUEST_ADDRINFO, -EBADMSG);
- q->ret = ai_resp->ret;
- q->_errno = ai_resp->_errno;
- q->_h_errno = ai_resp->_h_errno;
+ query_assign_errno(q, ai_resp->ret, ai_resp->_errno, ai_resp->_h_errno);
l = length - sizeof(AddrInfoResponse);
p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
@@ -806,9 +779,7 @@ static int handle_response(sd_resolve *resolve, const Packet *packet, size_t len
r = unserialize_addrinfo(&p, &l, &ai);
if (r < 0) {
- q->ret = EAI_SYSTEM;
- q->_errno = -r;
- q->_h_errno = 0;
+ query_assign_errno(q, EAI_SYSTEM, r, 0);
freeaddrinfo(q->addrinfo);
q->addrinfo = NULL;
break;
@@ -828,39 +799,28 @@ static int handle_response(sd_resolve *resolve, const Packet *packet, size_t len
case RESPONSE_NAMEINFO: {
const NameInfoResponse *ni_resp = &packet->nameinfo_response;
- assert(length >= sizeof(NameInfoResponse));
- assert(q->type == REQUEST_NAMEINFO);
+ assert_return(length >= sizeof(NameInfoResponse), -EBADMSG);
+ assert_return(q->type == REQUEST_NAMEINFO, -EBADMSG);
if (ni_resp->hostlen > DNS_HOSTNAME_MAX ||
ni_resp->servlen > DNS_HOSTNAME_MAX ||
- sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length + 2) {
- q->ret = EAI_SYSTEM;
- q->_errno = -EIO;
- q->_h_errno = 0;
-
- } else {
- q->ret = ni_resp->ret;
- q->_errno = ni_resp->_errno;
- q->_h_errno = ni_resp->_h_errno;
+ sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length)
+ query_assign_errno(q, EAI_SYSTEM, EIO, 0);
+ else {
+ query_assign_errno(q, ni_resp->ret, ni_resp->_errno, ni_resp->_h_errno);
if (ni_resp->hostlen > 0) {
q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse),
ni_resp->hostlen-1);
- if (!q->host) {
- q->ret = EAI_MEMORY;
- q->_errno = ENOMEM;
- q->_h_errno = 0;
- }
+ if (!q->host)
+ query_assign_errno(q, EAI_MEMORY, ENOMEM, 0);
}
if (ni_resp->servlen > 0) {
q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen,
ni_resp->servlen-1);
- if (!q->serv) {
- q->ret = EAI_MEMORY;
- q->_errno = ENOMEM;
- q->_h_errno = 0;
- }
+ if (!q->serv)
+ query_assign_errno(q, EAI_MEMORY, ENOMEM, 0);
}
}
@@ -888,7 +848,7 @@ _public_ int sd_resolve_process(sd_resolve *resolve) {
/* We don't allow recursively invoking sd_resolve_process(). */
assert_return(!resolve->current, -EBUSY);
- l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
+ l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof buf, 0);
if (l < 0) {
if (errno == EAGAIN)
return 0;
@@ -969,11 +929,12 @@ _public_ int sd_resolve_getaddrinfo(
const struct addrinfo *hints,
sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
- AddrInfoRequest req = {};
- struct msghdr mh = {};
+ _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
+ AddrInfoRequest req;
struct iovec iov[3];
- sd_resolve_query *q;
+ struct msghdr mh = {};
int r;
+ size_t node_len, service_len;
assert_return(resolve, -EINVAL);
assert_return(node || service, -EINVAL);
@@ -988,20 +949,23 @@ _public_ int sd_resolve_getaddrinfo(
q->getaddrinfo_handler = callback;
q->userdata = userdata;
- req.node_len = node ? strlen(node)+1 : 0;
- req.service_len = service ? strlen(service)+1 : 0;
+ node_len = node ? strlen(node) + 1 : 0;
+ service_len = service ? strlen(service) + 1 : 0;
- req.header.id = q->id;
- req.header.type = REQUEST_ADDRINFO;
- req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
+ req = (AddrInfoRequest) {
+ .node_len = node_len,
+ .service_len = service_len,
- if (hints) {
- req.hints_valid = true;
- req.ai_flags = hints->ai_flags;
- req.ai_family = hints->ai_family;
- req.ai_socktype = hints->ai_socktype;
- req.ai_protocol = hints->ai_protocol;
- }
+ .header.id = q->id,
+ .header.type = REQUEST_ADDRINFO,
+ .header.length = sizeof(AddrInfoRequest) + node_len + service_len,
+
+ .hints_valid = hints,
+ .ai_flags = hints ? hints->ai_flags : 0,
+ .ai_family = hints ? hints->ai_family : 0,
+ .ai_socktype = hints ? hints->ai_socktype : 0,
+ .ai_protocol = hints ? hints->ai_protocol : 0,
+ };
iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
if (node)
@@ -1010,15 +974,14 @@ _public_ int sd_resolve_getaddrinfo(
iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
mh.msg_iov = iov;
- if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
- sd_resolve_query_unref(q);
+ if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0)
return -errno;
- }
resolve->n_outstanding++;
if (_q)
*_q = q;
+ TAKE_PTR(q);
return 0;
}
@@ -1043,10 +1006,10 @@ _public_ int sd_resolve_getnameinfo(
sd_resolve_getnameinfo_handler_t callback,
void *userdata) {
- NameInfoRequest req = {};
- struct msghdr mh = {};
+ _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
+ NameInfoRequest req;
struct iovec iov[2];
- sd_resolve_query *q;
+ struct msghdr mh;
int r;
assert_return(resolve, -EINVAL);
@@ -1065,31 +1028,31 @@ _public_ int sd_resolve_getnameinfo(
q->getnameinfo_handler = callback;
q->userdata = userdata;
- req.header.id = q->id;
- req.header.type = REQUEST_NAMEINFO;
- req.header.length = sizeof(NameInfoRequest) + salen;
+ req = (NameInfoRequest) {
+ .header.id = q->id,
+ .header.type = REQUEST_NAMEINFO,
+ .header.length = sizeof(NameInfoRequest) + salen,
- req.flags = flags;
- req.sockaddr_len = salen;
- req.gethost = !!(get & SD_RESOLVE_GET_HOST);
- req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
+ .flags = flags,
+ .sockaddr_len = salen,
+ .gethost = !!(get & SD_RESOLVE_GET_HOST),
+ .getserv = !!(get & SD_RESOLVE_GET_SERVICE),
+ };
iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
- mh.msg_iov = iov;
- mh.msg_iovlen = 2;
+ mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov) };
- if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
- sd_resolve_query_unref(q);
+ if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0)
return -errno;
- }
-
- resolve->n_outstanding++;
if (_q)
*_q = q;
+ resolve->n_outstanding++;
+ TAKE_PTR(q);
+
return 0;
}
@@ -1100,7 +1063,7 @@ static int getnameinfo_done(sd_resolve_query *q) {
assert(q->getnameinfo_handler);
errno = q->_errno;
- h_errno= q->_h_errno;
+ h_errno = q->_h_errno;
return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
}
diff --git a/src/libsystemd/sd-resolve/test-resolve.c b/src/libsystemd/sd-resolve/test-resolve.c
index b728dee9dd..880d224a38 100644
--- a/src/libsystemd/sd-resolve/test-resolve.c
+++ b/src/libsystemd/sd-resolve/test-resolve.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2005-2008 Lennart Poettering
- Copyright 2014 Daniel Buch
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Daniel Buch
***/
#include <arpa/inet.h>
@@ -116,7 +100,6 @@ int main(int argc, char *argv[]) {
log_notice_errno(r, "sd_resolve_wait() timed out, but that's OK");
exit(EXIT_SUCCESS);
- break;
}
if (r < 0) {
log_error_errno(r, "sd_resolve_wait(): %m");
diff --git a/src/libsystemd/sd-utf8/sd-utf8.c b/src/libsystemd/sd-utf8/sd-utf8.c
index b8db7eb093..79909c9af1 100644
--- a/src/libsystemd/sd-utf8/sd-utf8.c
+++ b/src/libsystemd/sd-utf8/sd-utf8.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-utf8.h"
diff --git a/src/libudev/libudev-device-internal.h b/src/libudev/libudev-device-internal.h
index 445acd91a7..7a78deff79 100644
--- a/src/libudev/libudev-device-internal.h
+++ b/src/libudev/libudev-device-internal.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "sd-device.h"
diff --git a/src/libudev/libudev-device-private.c b/src/libudev/libudev-device-private.c
index 868926e72b..22b421299a 100644
--- a/src/libudev/libudev-device-private.c
+++ b/src/libudev/libudev-device-private.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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"
diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index 8e65cfd40a..0f132c54b5 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <dirent.h>
diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c
index 271880075e..c9d54dc72c 100644
--- a/src/libudev/libudev-enumerate.c
+++ b/src/libudev/libudev-enumerate.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -69,7 +50,6 @@ struct udev_enumerate {
**/
_public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
_cleanup_free_ struct udev_enumerate *udev_enumerate = NULL;
- struct udev_enumerate *ret;
int r;
assert_return_errno(udev, NULL, EINVAL);
@@ -97,10 +77,7 @@ _public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) {
udev_list_init(udev, &udev_enumerate->devices_list, false);
- ret = udev_enumerate;
- udev_enumerate = NULL;
-
- return ret;
+ return TAKE_PTR(udev_enumerate);
}
/**
diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c
index d2665278c1..45322677e9 100644
--- a/src/libudev/libudev-hwdb.c
+++ b/src/libudev/libudev-hwdb.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-hwdb.h"
@@ -73,8 +55,7 @@ _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
}
hwdb->refcount = 1;
- hwdb->hwdb = hwdb_internal;
- hwdb_internal = NULL;
+ hwdb->hwdb = TAKE_PTR(hwdb_internal);
udev_list_init(udev, &hwdb->properties_list, true);
diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c
index 681e2e445c..b7373efcda 100644
--- a/src/libudev/libudev-list.c
+++ b/src/libudev/libudev-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stddef.h>
diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c
index ca14373e19..bfad50c891 100644
--- a/src/libudev/libudev-monitor.c
+++ b/src/libudev/libudev-monitor.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <linux/filter.h>
diff --git a/src/libudev/libudev-private.h b/src/libudev/libudev-private.h
index 565da326f5..384be98e79 100644
--- a/src/libudev/libudev-private.h
+++ b/src/libudev/libudev-private.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <signal.h>
#include <stdbool.h>
diff --git a/src/libudev/libudev-queue.c b/src/libudev/libudev-queue.c
index 85ceb263a3..14e8a67e08 100644
--- a/src/libudev/libudev-queue.c
+++ b/src/libudev/libudev-queue.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk>
***/
#include <errno.h>
diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c
index 977caad86d..f80af9705e 100644
--- a/src/libudev/libudev-util.c
+++ b/src/libudev/libudev-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <ctype.h>
#include <errno.h>
diff --git a/src/libudev/libudev.c b/src/libudev/libudev.c
index 64904c5ffa..8af97fe16d 100644
--- a/src/libudev/libudev.c
+++ b/src/libudev/libudev.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2014 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 <ctype.h>
#include <stdarg.h>
@@ -85,8 +67,7 @@ _public_ void udev_set_userdata(struct udev *udev, void *userdata) {
/**
* udev_new:
*
- * Create udev library context. This reads the udev configuration
- * file, and fills in the default values.
+ * Create udev library context. This only allocates the basic data structure.
*
* The initial refcount is 1, and needs to be decremented to
* release the resources of the udev library context.
diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h
index be465a0043..fa4eaeb969 100644
--- a/src/libudev/libudev.h
+++ b/src/libudev/libudev.h
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#ifndef _LIBUDEV_H_
#define _LIBUDEV_H_
@@ -200,7 +182,6 @@ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hw
*/
int udev_util_encode_string(const char *str, char *str_enc, size_t len);
-
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/src/libudev/libudev.sym b/src/libudev/libudev.sym
index 1e8dbfa056..fb2e03e432 100644
--- a/src/libudev/libudev.sym
+++ b/src/libudev/libudev.sym
@@ -1,8 +1,6 @@
/***
SPDX-License-Identifier: LGPL-2.1+
- 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
diff --git a/src/libudev/meson.build b/src/libudev/meson.build
index c381352ce8..323c7e97d0 100644
--- a/src/libudev/meson.build
+++ b/src/libudev/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
libudev_sources = files('''
libudev-private.h
diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c
index 2d788106bb..598b931d03 100644
--- a/src/locale/keymap-util.c
+++ b/src/locale/keymap-util.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 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 <errno.h>
#include <stdio_ext.h>
@@ -93,39 +74,64 @@ void context_free(Context *c) {
context_free_vconsole(c);
};
-void locale_simplify(Context *c) {
+void locale_simplify(char *locale[_VARIABLE_LC_MAX]) {
int p;
for (p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++)
- if (isempty(c->locale[p]) || streq_ptr(c->locale[VARIABLE_LANG], c->locale[p]))
- c->locale[p] = mfree(c->locale[p]);
+ if (isempty(locale[p]) || streq_ptr(locale[VARIABLE_LANG], locale[p]))
+ locale[p] = mfree(locale[p]);
}
-static int locale_read_data(Context *c) {
+int locale_read_data(Context *c, sd_bus_message *m) {
+ struct stat st;
int r;
- context_free_locale(c);
+ /* Do not try to re-read the file within single bus operation. */
+ if (m && m == c->locale_cache)
+ return 0;
- r = parse_env_file("/etc/locale.conf", NEWLINE,
- "LANG", &c->locale[VARIABLE_LANG],
- "LANGUAGE", &c->locale[VARIABLE_LANGUAGE],
- "LC_CTYPE", &c->locale[VARIABLE_LC_CTYPE],
- "LC_NUMERIC", &c->locale[VARIABLE_LC_NUMERIC],
- "LC_TIME", &c->locale[VARIABLE_LC_TIME],
- "LC_COLLATE", &c->locale[VARIABLE_LC_COLLATE],
- "LC_MONETARY", &c->locale[VARIABLE_LC_MONETARY],
- "LC_MESSAGES", &c->locale[VARIABLE_LC_MESSAGES],
- "LC_PAPER", &c->locale[VARIABLE_LC_PAPER],
- "LC_NAME", &c->locale[VARIABLE_LC_NAME],
- "LC_ADDRESS", &c->locale[VARIABLE_LC_ADDRESS],
- "LC_TELEPHONE", &c->locale[VARIABLE_LC_TELEPHONE],
- "LC_MEASUREMENT", &c->locale[VARIABLE_LC_MEASUREMENT],
- "LC_IDENTIFICATION", &c->locale[VARIABLE_LC_IDENTIFICATION],
- NULL);
+ /* To suppress multiple call of stat(), store the message to cache here. */
+ c->locale_cache = m;
+
+ r = stat("/etc/locale.conf", &st);
+ if (r < 0 && errno != ENOENT)
+ return -errno;
- if (r == -ENOENT) {
+ if (r >= 0) {
+ usec_t t;
+
+ /* If mtime is not changed, then we do not need to re-read the file. */
+ t = timespec_load(&st.st_mtim);
+ if (c->locale_mtime != USEC_INFINITY && t == c->locale_mtime)
+ return 0;
+
+ c->locale_mtime = t;
+ context_free_locale(c);
+
+ r = parse_env_file(NULL, "/etc/locale.conf", NEWLINE,
+ "LANG", &c->locale[VARIABLE_LANG],
+ "LANGUAGE", &c->locale[VARIABLE_LANGUAGE],
+ "LC_CTYPE", &c->locale[VARIABLE_LC_CTYPE],
+ "LC_NUMERIC", &c->locale[VARIABLE_LC_NUMERIC],
+ "LC_TIME", &c->locale[VARIABLE_LC_TIME],
+ "LC_COLLATE", &c->locale[VARIABLE_LC_COLLATE],
+ "LC_MONETARY", &c->locale[VARIABLE_LC_MONETARY],
+ "LC_MESSAGES", &c->locale[VARIABLE_LC_MESSAGES],
+ "LC_PAPER", &c->locale[VARIABLE_LC_PAPER],
+ "LC_NAME", &c->locale[VARIABLE_LC_NAME],
+ "LC_ADDRESS", &c->locale[VARIABLE_LC_ADDRESS],
+ "LC_TELEPHONE", &c->locale[VARIABLE_LC_TELEPHONE],
+ "LC_MEASUREMENT", &c->locale[VARIABLE_LC_MEASUREMENT],
+ "LC_IDENTIFICATION", &c->locale[VARIABLE_LC_IDENTIFICATION],
+ NULL);
+ if (r < 0)
+ return r;
+ } else {
int p;
+ c->locale_mtime = USEC_INFINITY;
+ context_free_locale(c);
+
/* Fill in what we got passed from systemd. */
for (p = 0; p < _VARIABLE_LC_MAX; p++) {
const char *name;
@@ -137,41 +143,86 @@ static int locale_read_data(Context *c) {
if (r < 0)
return r;
}
-
- r = 0;
}
- locale_simplify(c);
- return r;
+ locale_simplify(c->locale);
+ return 0;
}
-static int vconsole_read_data(Context *c) {
+int vconsole_read_data(Context *c, sd_bus_message *m) {
+ struct stat st;
+ usec_t t;
int r;
+ /* Do not try to re-read the file within single bus operation. */
+ if (m && m == c->vc_cache)
+ return 0;
+
+ /* To suppress multiple call of stat(), store the message to cache here. */
+ c->vc_cache = m;
+
+ if (stat("/etc/vconsole.conf", &st) < 0) {
+ if (errno != ENOENT)
+ return -errno;
+
+ c->vc_mtime = USEC_INFINITY;
+ context_free_vconsole(c);
+ return 0;
+ }
+
+ /* If mtime is not changed, then we do not need to re-read */
+ t = timespec_load(&st.st_mtim);
+ if (c->vc_mtime != USEC_INFINITY && t == c->vc_mtime)
+ return 0;
+
+ c->vc_mtime = t;
context_free_vconsole(c);
- r = parse_env_file("/etc/vconsole.conf", NEWLINE,
+ r = parse_env_file(NULL, "/etc/vconsole.conf", NEWLINE,
"KEYMAP", &c->vc_keymap,
"KEYMAP_TOGGLE", &c->vc_keymap_toggle,
NULL);
-
- if (r < 0 && r != -ENOENT)
+ if (r < 0)
return r;
return 0;
}
-static int x11_read_data(Context *c) {
- _cleanup_fclose_ FILE *f;
- char line[LINE_MAX];
+int x11_read_data(Context *c, sd_bus_message *m) {
+ _cleanup_fclose_ FILE *f = NULL;
bool in_section = false;
+ char line[LINE_MAX];
+ struct stat st;
+ usec_t t;
int r;
+ /* Do not try to re-read the file within single bus operation. */
+ if (m && m == c->x11_cache)
+ return 0;
+
+ /* To suppress multiple call of stat(), store the message to cache here. */
+ c->x11_cache = m;
+
+ if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) < 0) {
+ if (errno != ENOENT)
+ return -errno;
+
+ c->x11_mtime = USEC_INFINITY;
+ context_free_x11(c);
+ return 0;
+ }
+
+ /* If mtime is not changed, then we do not need to re-read */
+ t = timespec_load(&st.st_mtim);
+ if (c->x11_mtime != USEC_INFINITY && t == c->x11_mtime)
+ return 0;
+
+ c->x11_mtime = t;
context_free_x11(c);
f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
if (!f)
- return errno == ENOENT ? 0 : -errno;
+ return -errno;
while (fgets(line, sizeof(line), f)) {
char *l;
@@ -223,26 +274,13 @@ static int x11_read_data(Context *c) {
return 0;
}
-int context_read_data(Context *c) {
- int r, q, p;
-
- r = locale_read_data(c);
- q = vconsole_read_data(c);
- p = x11_read_data(c);
-
- return r < 0 ? r : q < 0 ? q : p;
-}
-
int locale_write_data(Context *c, char ***settings) {
- int r, p;
_cleanup_strv_free_ char **l = NULL;
+ struct stat st;
+ int r, p;
/* Set values will be returned as strv in *settings on success. */
- r = load_env_file(NULL, "/etc/locale.conf", NULL, &l);
- if (r < 0 && r != -ENOENT)
- return r;
-
for (p = 0; p < _VARIABLE_LC_MAX; p++) {
_cleanup_free_ char *t = NULL;
char **u;
@@ -251,10 +289,8 @@ int locale_write_data(Context *c, char ***settings) {
name = locale_variable_to_string(p);
assert(name);
- if (isempty(c->locale[p])) {
- l = strv_env_unset(l, name);
+ if (isempty(c->locale[p]))
continue;
- }
if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0)
return -ENOMEM;
@@ -263,14 +299,14 @@ int locale_write_data(Context *c, char ***settings) {
if (!u)
return -ENOMEM;
- strv_free(l);
- l = u;
+ strv_free_and_replace(l, u);
}
if (strv_isempty(l)) {
if (unlink("/etc/locale.conf") < 0)
return errno == ENOENT ? 0 : -errno;
+ c->locale_mtime = USEC_INFINITY;
return 0;
}
@@ -278,14 +314,18 @@ int locale_write_data(Context *c, char ***settings) {
if (r < 0)
return r;
- *settings = l;
- l = NULL;
+ *settings = TAKE_PTR(l);
+
+ if (stat("/etc/locale.conf", &st) >= 0)
+ c->locale_mtime = timespec_load(&st.st_mtim);
+
return 0;
}
int vconsole_write_data(Context *c) {
- int r;
_cleanup_strv_free_ char **l = NULL;
+ struct stat st;
+ int r;
r = load_env_file(NULL, "/etc/vconsole.conf", NULL, &l);
if (r < 0 && r != -ENOENT)
@@ -305,8 +345,7 @@ int vconsole_write_data(Context *c) {
if (!u)
return -ENOMEM;
- strv_free(l);
- l = u;
+ strv_free_and_replace(l, u);
}
if (isempty(c->vc_keymap_toggle))
@@ -323,23 +362,31 @@ int vconsole_write_data(Context *c) {
if (!u)
return -ENOMEM;
- strv_free(l);
- l = u;
+ strv_free_and_replace(l, u);
}
if (strv_isempty(l)) {
if (unlink("/etc/vconsole.conf") < 0)
return errno == ENOENT ? 0 : -errno;
+ c->vc_mtime = USEC_INFINITY;
return 0;
}
- return write_env_file_label("/etc/vconsole.conf", l);
+ r = write_env_file_label("/etc/vconsole.conf", l);
+ if (r < 0)
+ return r;
+
+ if (stat("/etc/vconsole.conf", &st) >= 0)
+ c->vc_mtime = timespec_load(&st.st_mtim);
+
+ return 0;
}
int x11_write_data(Context *c) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *temp_path = NULL;
+ struct stat st;
int r;
if (isempty(c->x11_layout) &&
@@ -350,6 +397,7 @@ int x11_write_data(Context *c) {
if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
return errno == ENOENT ? 0 : -errno;
+ c->vc_mtime = USEC_INFINITY;
return 0;
}
@@ -392,6 +440,9 @@ int x11_write_data(Context *c) {
goto fail;
}
+ if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) >= 0)
+ c->x11_mtime = timespec_load(&st.st_mtim);
+
return 0;
fail:
@@ -539,8 +590,7 @@ int find_converted_keymap(const char *x11_layout, const char *x11_variant, char
log_debug("Found converted keymap %s at %s",
n, uncompressed ? p : pz);
- *new_keymap = n;
- n = NULL;
+ *new_keymap = TAKE_PTR(n);
return 1;
}
}
@@ -548,9 +598,10 @@ int find_converted_keymap(const char *x11_layout, const char *x11_variant, char
return 0;
}
-int find_legacy_keymap(Context *c, char **new_keymap) {
+int find_legacy_keymap(Context *c, char **ret) {
const char *map;
_cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *new_keymap = NULL;
unsigned n = 0;
unsigned best_matching = 0;
int r;
@@ -615,7 +666,7 @@ int find_legacy_keymap(Context *c, char **new_keymap) {
if (matching > best_matching) {
best_matching = matching;
- r = free_and_strdup(new_keymap, a[0]);
+ r = free_and_strdup(&new_keymap, a[0]);
if (r < 0)
return r;
}
@@ -635,13 +686,12 @@ int find_legacy_keymap(Context *c, char **new_keymap) {
r = find_converted_keymap(l, v, &converted);
if (r < 0)
return r;
- if (r > 0) {
- free(*new_keymap);
- *new_keymap = converted;
- }
+ if (r > 0)
+ free_and_replace(new_keymap, converted);
}
- return (bool) *new_keymap;
+ *ret = TAKE_PTR(new_keymap);
+ return (bool) *ret;
}
int find_language_fallback(const char *lang, char **language) {
@@ -668,8 +718,7 @@ int find_language_fallback(const char *lang, char **language) {
if (streq(lang, a[0])) {
assert(strv_length(a) == 2);
- *language = a[1];
- a[1] = NULL;
+ *language = TAKE_PTR(a[1]);
return 1;
}
}
@@ -687,7 +736,7 @@ int x11_convert_to_vconsole(Context *c) {
context_free_vconsole(c);
} else {
- char *new_keymap = NULL;
+ _cleanup_free_ char *new_keymap = NULL;
int r;
r = find_converted_keymap(c->x11_layout, c->x11_variant, &new_keymap);
@@ -706,12 +755,10 @@ int x11_convert_to_vconsole(Context *c) {
c->x11_layout);
if (!streq_ptr(c->vc_keymap, new_keymap)) {
- free(c->vc_keymap);
- c->vc_keymap = new_keymap;
+ free_and_replace(c->vc_keymap, new_keymap);
c->vc_keymap_toggle = mfree(c->vc_keymap_toggle);
modified = true;
- } else
- free(new_keymap);
+ }
}
if (modified)
diff --git a/src/locale/keymap-util.h b/src/locale/keymap-util.h
index 371bbf2622..c55c9f92a6 100644
--- a/src/locale/keymap-util.h
+++ b/src/locale/keymap-util.h
@@ -1,34 +1,24 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
- Copyright 2011 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 "sd-bus.h"
#include "locale-util.h"
+#include "time-util.h"
typedef struct Context {
+ sd_bus_message *locale_cache;
+ usec_t locale_mtime;
char *locale[_VARIABLE_LC_MAX];
+ sd_bus_message *x11_cache;
+ usec_t x11_mtime;
char *x11_layout;
char *x11_model;
char *x11_variant;
char *x11_options;
+ sd_bus_message *vc_cache;
+ usec_t vc_mtime;
char *vc_keymap;
char *vc_keymap_toggle;
} Context;
@@ -37,11 +27,14 @@ int find_converted_keymap(const char *x11_layout, const char *x11_variant, char
int find_legacy_keymap(Context *c, char **new_keymap);
int find_language_fallback(const char *lang, char **language);
-int context_read_data(Context *c);
+int locale_read_data(Context *c, sd_bus_message *m);
+int vconsole_read_data(Context *c, sd_bus_message *m);
+int x11_read_data(Context *c, sd_bus_message *m);
+
void context_free(Context *c);
int vconsole_convert_to_x11(Context *c);
int vconsole_write_data(Context *c);
int x11_convert_to_vconsole(Context *c);
int x11_write_data(Context *c);
-void locale_simplify(Context *c);
+void locale_simplify(char *locale[_VARIABLE_LC_MAX]);
int locale_write_data(Context *c, char ***settings);
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index af39e431f5..b3ad2820d9 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 <ftw.h>
#include <getopt.h>
@@ -39,6 +20,7 @@
#include "spawn-polkit-agent.h"
#include "strv.h"
#include "util.h"
+#include "verbs.h"
#include "virt.h"
static bool arg_no_pager = false;
@@ -49,23 +31,17 @@ static bool arg_convert = true;
typedef struct StatusInfo {
char **locale;
- char *vconsole_keymap;
- char *vconsole_keymap_toggle;
- char *x11_layout;
- char *x11_model;
- char *x11_variant;
- char *x11_options;
+ const char *vconsole_keymap;
+ const char *vconsole_keymap_toggle;
+ const char *x11_layout;
+ const char *x11_model;
+ const char *x11_variant;
+ const char *x11_options;
} StatusInfo;
static void status_info_clear(StatusInfo *info) {
if (info) {
strv_free(info->locale);
- free(info->vconsole_keymap);
- free(info->vconsole_keymap_toggle);
- free(info->x11_layout);
- free(info->x11_model);
- free(info->x11_variant);
- free(info->x11_options);
zero(*info);
}
}
@@ -79,7 +55,7 @@ static void print_overridden_variables(void) {
if (detect_container() > 0 || arg_host)
return;
- r = parse_env_file("/proc/cmdline", WHITESPACE,
+ r = parse_env_file(NULL, "/proc/cmdline", WHITESPACE,
"locale.LANG", &variables[VARIABLE_LANG],
"locale.LANGUAGE", &variables[VARIABLE_LANGUAGE],
"locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
@@ -142,11 +118,10 @@ static void print_status_info(StatusInfo *i) {
printf(" X11 Options: %s\n", i->x11_options);
}
-static int show_status(sd_bus *bus, char **args, unsigned n) {
+static int show_status(int argc, char **argv, void *userdata) {
_cleanup_(status_info_clear) StatusInfo info = {};
static const struct bus_properties_map map[] = {
{ "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
- { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
{ "VConsoleKeymapToggle", "s", NULL, offsetof(StatusInfo, vconsole_keymap_toggle) },
{ "X11Layout", "s", NULL, offsetof(StatusInfo, x11_layout) },
{ "X11Model", "s", NULL, offsetof(StatusInfo, x11_model) },
@@ -157,6 +132,8 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ sd_bus *bus = userdata;
int r;
assert(bus);
@@ -165,7 +142,9 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
"org.freedesktop.locale1",
"/org/freedesktop/locale1",
map,
+ 0,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -176,13 +155,13 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int set_locale(sd_bus *bus, char **args, unsigned n) {
+static int set_locale(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
assert(bus);
- assert(args);
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
@@ -196,7 +175,7 @@ static int set_locale(sd_bus *bus, char **args, unsigned n) {
if (r < 0)
return bus_log_create_error(r);
- r = sd_bus_message_append_strv(m, args + 1);
+ r = sd_bus_message_append_strv(m, argv + 1);
if (r < 0)
return bus_log_create_error(r);
@@ -213,39 +192,32 @@ static int set_locale(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int list_locales(sd_bus *bus, char **args, unsigned n) {
+static int list_locales(int argc, char **argv, void *userdata) {
_cleanup_strv_free_ char **l = NULL;
int r;
- assert(args);
-
r = get_locales(&l);
if (r < 0)
return log_error_errno(r, "Failed to read list of locales: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
strv_print(l);
return 0;
}
-static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
+static int set_vconsole_keymap(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *map, *toggle_map;
+ sd_bus *bus = userdata;
int r;
assert(bus);
- assert(args);
-
- if (n > 3) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- map = args[1];
- toggle_map = n > 2 ? args[2] : "";
+ map = argv[1];
+ toggle_map = argc > 2 ? argv[2] : "";
r = sd_bus_call_method(
bus,
@@ -262,42 +234,33 @@ static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
+static int list_vconsole_keymaps(int argc, char **argv, void *userdata) {
_cleanup_strv_free_ char **l = NULL;
int r;
- assert(args);
-
r = get_keymaps(&l);
if (r < 0)
return log_error_errno(r, "Failed to read list of keymaps: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
strv_print(l);
return 0;
}
-static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
+static int set_x11_keymap(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *layout, *model, *variant, *options;
+ sd_bus *bus = userdata;
int r;
- assert(bus);
- assert(args);
-
- if (n > 5) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- layout = args[1];
- model = n > 2 ? args[2] : "";
- variant = n > 3 ? args[3] : "";
- options = n > 4 ? args[4] : "";
+ layout = argv[1];
+ model = argc > 2 ? argv[2] : "";
+ variant = argc > 3 ? argv[3] : "";
+ options = argc > 4 ? argv[4] : "";
r = sd_bus_call_method(
bus,
@@ -315,7 +278,7 @@ static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
+static int list_x11_keymaps(int argc, char **argv, void *userdata) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **list = NULL;
char line[LINE_MAX];
@@ -328,22 +291,17 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
} state = NONE, look_for;
int r;
- if (n > 2) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
f = fopen("/usr/share/X11/xkb/rules/base.lst", "re");
if (!f)
return log_error_errno(errno, "Failed to open keyboard mapping list. %m");
- if (streq(args[0], "list-x11-keymap-models"))
+ if (streq(argv[0], "list-x11-keymap-models"))
look_for = MODELS;
- else if (streq(args[0], "list-x11-keymap-layouts"))
+ else if (streq(argv[0], "list-x11-keymap-layouts"))
look_for = LAYOUTS;
- else if (streq(args[0], "list-x11-keymap-variants"))
+ else if (streq(argv[0], "list-x11-keymap-variants"))
look_for = VARIANTS;
- else if (streq(args[0], "list-x11-keymap-options"))
+ else if (streq(argv[0], "list-x11-keymap-options"))
look_for = OPTIONS;
else
assert_not_reached("Wrong parameter");
@@ -376,7 +334,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
w = l + strcspn(l, WHITESPACE);
- if (n > 1) {
+ if (argc > 1) {
char *e;
if (*w == 0)
@@ -392,7 +350,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
*e = 0;
- if (!streq(w, args[1]))
+ if (!streq(w, argv[1]))
continue;
} else
*w = 0;
@@ -410,13 +368,13 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
strv_sort(list);
strv_uniq(list);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
strv_print(list);
return 0;
}
-static void help(void) {
+static int help(void) {
printf("%s [OPTIONS...] COMMAND ...\n\n"
"Query or change system locale and keyboard settings.\n\n"
" -h --help Show this help\n"
@@ -440,6 +398,12 @@ static void help(void) {
" Show known X11 keyboard mapping variants\n"
" list-x11-keymap-options Show known X11 keyboard mapping options\n"
, program_invocation_short_name);
+
+ return 0;
+}
+
+static int verb_help(int argc, char **argv, void *userdata) {
+ return help();
}
static int parse_argv(int argc, char *argv[]) {
@@ -472,8 +436,7 @@ static int parse_argv(int argc, char *argv[]) {
switch (c) {
case 'h':
- help();
- return 0;
+ return help();
case ARG_VERSION:
return version();
@@ -512,86 +475,22 @@ static int parse_argv(int argc, char *argv[]) {
static int localectl_main(sd_bus *bus, int argc, char *argv[]) {
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-locale", MORE, 2, set_locale },
- { "list-locales", EQUAL, 1, list_locales },
- { "set-keymap", MORE, 2, set_vconsole_keymap },
- { "list-keymaps", EQUAL, 1, list_vconsole_keymaps },
- { "set-x11-keymap", MORE, 2, set_x11_keymap },
- { "list-x11-keymap-models", EQUAL, 1, list_x11_keymaps },
- { "list-x11-keymap-layouts", EQUAL, 1, list_x11_keymaps },
- { "list-x11-keymap-variants", LESS, 2, list_x11_keymaps },
- { "list-x11-keymap-options", EQUAL, 1, list_x11_keymaps },
+ static const Verb verbs[] = {
+ { "status", VERB_ANY, 1, VERB_DEFAULT, show_status },
+ { "set-locale", 2, VERB_ANY, 0, set_locale },
+ { "list-locales", VERB_ANY, 1, 0, list_locales },
+ { "set-keymap", 2, 3, 0, set_vconsole_keymap },
+ { "list-keymaps", VERB_ANY, 1, 0, list_vconsole_keymaps },
+ { "set-x11-keymap", 2, 5, 0, set_x11_keymap },
+ { "list-x11-keymap-models", VERB_ANY, 1, 0, list_x11_keymaps },
+ { "list-x11-keymap-layouts", VERB_ANY, 1, 0, list_x11_keymaps },
+ { "list-x11-keymap-variants", VERB_ANY, 2, 0, list_x11_keymaps },
+ { "list-x11-keymap-options", VERB_ANY, 1, 0, list_x11_keymaps },
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */
+ {}
};
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
+ return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char*argv[]) {
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 02f5e8c656..b8f95b69a6 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 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 <errno.h>
#include <string.h>
@@ -101,7 +82,7 @@ static int locale_update_system_manager(Context *c, sd_bus *bus) {
r = sd_bus_call(bus, m, 0, &error, NULL);
if (r < 0)
- log_error_errno(r, "Failed to update the manager environment: %m");
+ log_error_errno(r, "Failed to update the manager environment, ignoring: %m");
return 0;
}
@@ -126,10 +107,14 @@ static int vconsole_reload(sd_bus *bus) {
return r;
}
-static int vconsole_convert_to_x11_and_emit(Context *c, sd_bus *bus) {
+static int vconsole_convert_to_x11_and_emit(Context *c, sd_bus_message *m) {
int r;
- assert(bus);
+ assert(m);
+
+ r = x11_read_data(c, m);
+ if (r < 0)
+ return r;
r = vconsole_convert_to_x11(c);
if (r <= 0)
@@ -140,7 +125,7 @@ static int vconsole_convert_to_x11_and_emit(Context *c, sd_bus *bus) {
if (r < 0)
return log_error_errno(r, "Failed to write X11 keyboard layout: %m");
- sd_bus_emit_properties_changed(bus,
+ sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
"/org/freedesktop/locale1",
"org.freedesktop.locale1",
"X11Layout", "X11Model", "X11Variant", "X11Options", NULL);
@@ -148,10 +133,14 @@ static int vconsole_convert_to_x11_and_emit(Context *c, sd_bus *bus) {
return 1;
}
-static int x11_convert_to_vconsole_and_emit(Context *c, sd_bus *bus) {
+static int x11_convert_to_vconsole_and_emit(Context *c, sd_bus_message *m) {
int r;
- assert(bus);
+ assert(m);
+
+ r = vconsole_read_data(c, m);
+ if (r < 0)
+ return r;
r = x11_convert_to_vconsole(c);
if (r <= 0)
@@ -162,12 +151,12 @@ static int x11_convert_to_vconsole_and_emit(Context *c, sd_bus *bus) {
if (r < 0)
log_error_errno(r, "Failed to save virtual console keymap: %m");
- sd_bus_emit_properties_changed(bus,
+ sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
"/org/freedesktop/locale1",
"org.freedesktop.locale1",
"VConsoleKeymap", "VConsoleKeymapToggle", NULL);
- return vconsole_reload(bus);
+ return vconsole_reload(sd_bus_message_get_bus(m));
}
static int property_get_locale(
@@ -181,7 +170,11 @@ static int property_get_locale(
Context *c = userdata;
_cleanup_strv_free_ char **l = NULL;
- int p, q;
+ int p, q, r;
+
+ r = locale_read_data(c, reply);
+ if (r < 0)
+ return r;
l = new0(char*, _VARIABLE_LC_MAX+1);
if (!l)
@@ -206,16 +199,72 @@ static int property_get_locale(
return sd_bus_message_append_strv(reply, l);
}
+static int property_get_vconsole(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Context *c = userdata;
+ int r;
+
+ r = vconsole_read_data(c, reply);
+ if (r < 0)
+ return r;
+
+ if (streq(property, "VConsoleKeymap"))
+ return sd_bus_message_append_basic(reply, 's', c->vc_keymap);
+ else if (streq(property, "VConsoleKeymapToggle"))
+ return sd_bus_message_append_basic(reply, 's', c->vc_keymap_toggle);
+
+ return -EINVAL;
+}
+
+static int property_get_xkb(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Context *c = userdata;
+ int r;
+
+ r = x11_read_data(c, reply);
+ if (r < 0)
+ return r;
+
+ if (streq(property, "X11Layout"))
+ return sd_bus_message_append_basic(reply, 's', c->x11_layout);
+ else if (streq(property, "X11Model"))
+ return sd_bus_message_append_basic(reply, 's', c->x11_model);
+ else if (streq(property, "X11Variant"))
+ return sd_bus_message_append_basic(reply, 's', c->x11_variant);
+ else if (streq(property, "X11Options"))
+ return sd_bus_message_append_basic(reply, 's', c->x11_options);
+
+ return -EINVAL;
+}
+
+static void locale_free(char ***l) {
+ int p;
+
+ for (p = 0; p < _VARIABLE_LC_MAX; p++)
+ (*l)[p] = mfree((*l)[p]);
+}
+
static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Context *c = userdata;
- _cleanup_strv_free_ char **l = NULL;
- char **i;
- const char *lang = NULL;
- int interactive;
+ _cleanup_strv_free_ char **settings = NULL, **l = NULL;
+ char *new_locale[_VARIABLE_LC_MAX] = {}, **i;
+ _cleanup_(locale_free) _unused_ char **dummy = new_locale;
bool modified = false;
- bool have[_VARIABLE_LC_MAX] = {};
- int p;
- int r;
+ int interactive, p, r;
assert(m);
assert(c);
@@ -228,7 +277,19 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
if (r < 0)
return r;
- /* Check whether a variable changed and if it is valid */
+ /* If single locale without variable name is provided, then we assume it is LANG=. */
+ if (strv_length(l) == 1 && !strchr(*l, '=')) {
+ if (!locale_is_valid(*l))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
+
+ new_locale[VARIABLE_LANG] = strdup(*l);
+ if (!new_locale[VARIABLE_LANG])
+ return -ENOMEM;
+
+ l = strv_free(l);
+ }
+
+ /* Check whether a variable is valid */
STRV_FOREACH(i, l) {
bool valid = false;
@@ -244,13 +305,10 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
(*i)[k] == '=' &&
locale_is_valid((*i) + k + 1)) {
valid = true;
- have[p] = true;
- if (p == VARIABLE_LANG)
- lang = (*i) + k + 1;
-
- if (!streq_ptr(*i + k + 1, c->locale[p]))
- modified = true;
+ new_locale[p] = strdup((*i) + k + 1);
+ if (!new_locale[p])
+ return -ENOMEM;
break;
}
@@ -262,100 +320,82 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
/* If LANG was specified, but not LANGUAGE, check if we should
* set it based on the language fallback table. */
- if (have[VARIABLE_LANG] && !have[VARIABLE_LANGUAGE]) {
+ if (!isempty(new_locale[VARIABLE_LANG]) &&
+ isempty(new_locale[VARIABLE_LANGUAGE])) {
_cleanup_free_ char *language = NULL;
- assert(lang);
-
- (void) find_language_fallback(lang, &language);
+ (void) find_language_fallback(new_locale[VARIABLE_LANG], &language);
if (language) {
- log_debug("Converted LANG=%s to LANGUAGE=%s", lang, language);
- if (!streq_ptr(language, c->locale[VARIABLE_LANGUAGE])) {
- r = strv_extendf(&l, "LANGUAGE=%s", language);
- if (r < 0)
- return r;
-
- have[VARIABLE_LANGUAGE] = true;
- modified = true;
- }
+ log_debug("Converted LANG=%s to LANGUAGE=%s", new_locale[VARIABLE_LANG], language);
+ free_and_replace(new_locale[VARIABLE_LANGUAGE], language);
}
}
- /* Check whether a variable is unset */
- if (!modified)
- for (p = 0; p < _VARIABLE_LC_MAX; p++)
- if (!isempty(c->locale[p]) && !have[p]) {
- modified = true;
- break;
- }
+ r = locale_read_data(c, m);
+ if (r < 0) {
+ log_error_errno(r, "Failed to read locale data: %m");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to read locale data");
+ }
- if (modified) {
- _cleanup_strv_free_ char **settings = NULL;
-
- r = bus_verify_polkit_async(
- m,
- CAP_SYS_ADMIN,
- "org.freedesktop.locale1.set-locale",
- NULL,
- interactive,
- UID_INVALID,
- &polkit_registry,
- error);
- if (r < 0)
- return r;
- if (r == 0)
- return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
-
- STRV_FOREACH(i, l)
- for (p = 0; p < _VARIABLE_LC_MAX; p++) {
- size_t k;
- const char *name;
-
- name = locale_variable_to_string(p);
- assert(name);
-
- k = strlen(name);
- if (startswith(*i, name) && (*i)[k] == '=') {
- r = free_and_strdup(&c->locale[p], *i + k + 1);
- if (r < 0)
- return r;
- break;
- }
- }
+ /* Merge with the current settings */
+ for (p = 0; p < _VARIABLE_LC_MAX; p++)
+ if (!isempty(c->locale[p]) && isempty(new_locale[p])) {
+ new_locale[p] = strdup(c->locale[p]);
+ if (!new_locale[p])
+ return -ENOMEM;
+ }
- for (p = 0; p < _VARIABLE_LC_MAX; p++) {
- if (have[p])
- continue;
+ locale_simplify(new_locale);
- c->locale[p] = mfree(c->locale[p]);
+ for (p = 0; p < _VARIABLE_LC_MAX; p++)
+ if (!streq_ptr(c->locale[p], new_locale[p])) {
+ modified = true;
+ break;
}
- locale_simplify(c);
+ if (!modified) {
+ log_debug("Locale settings were not modified.");
+ return sd_bus_reply_method_return(m, NULL);
+ }
- r = locale_write_data(c, &settings);
- if (r < 0) {
- log_error_errno(r, "Failed to set locale: %m");
- return sd_bus_error_set_errnof(error, r, "Failed to set locale: %m");
- }
+ r = bus_verify_polkit_async(
+ m,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.locale1.set-locale",
+ NULL,
+ interactive,
+ UID_INVALID,
+ &polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- locale_update_system_manager(c, sd_bus_message_get_bus(m));
+ for (p = 0; p < _VARIABLE_LC_MAX; p++)
+ free_and_replace(c->locale[p], new_locale[p]);
+
+ r = locale_write_data(c, &settings);
+ if (r < 0) {
+ log_error_errno(r, "Failed to set locale: %m");
+ return sd_bus_error_set_errnof(error, r, "Failed to set locale: %m");
+ }
- if (settings) {
- _cleanup_free_ char *line;
+ (void) locale_update_system_manager(c, sd_bus_message_get_bus(m));
- line = strv_join(settings, ", ");
- log_info("Changed locale to %s.", strnull(line));
- } else
- log_info("Changed locale to unset.");
+ if (settings) {
+ _cleanup_free_ char *line;
- (void) sd_bus_emit_properties_changed(
- sd_bus_message_get_bus(m),
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "Locale", NULL);
+ line = strv_join(settings, ", ");
+ log_info("Changed locale to %s.", strnull(line));
} else
- log_debug("Locale settings were not modified.");
+ log_info("Changed locale to unset.");
+ (void) sd_bus_emit_properties_changed(
+ sd_bus_message_get_bus(m),
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ "Locale", NULL);
return sd_bus_reply_method_return(m, NULL);
}
@@ -363,8 +403,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Context *c = userdata;
const char *keymap, *keymap_toggle;
- int convert, interactive;
- int r;
+ int convert, interactive, r;
assert(m);
assert(c);
@@ -376,55 +415,61 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro
keymap = empty_to_null(keymap);
keymap_toggle = empty_to_null(keymap_toggle);
- if (!streq_ptr(keymap, c->vc_keymap) ||
- !streq_ptr(keymap_toggle, c->vc_keymap_toggle)) {
-
- if ((keymap && (!filename_is_valid(keymap) || !string_is_safe(keymap))) ||
- (keymap_toggle && (!filename_is_valid(keymap_toggle) || !string_is_safe(keymap_toggle))))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keymap data");
-
- r = bus_verify_polkit_async(
- m,
- CAP_SYS_ADMIN,
- "org.freedesktop.locale1.set-keyboard",
- NULL,
- interactive,
- UID_INVALID,
- &polkit_registry,
- error);
- if (r < 0)
- return r;
- if (r == 0)
- return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+ r = vconsole_read_data(c, m);
+ if (r < 0) {
+ log_error_errno(r, "Failed to read virtual console keymap data: %m");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to read virtual console keymap data");
+ }
- if (free_and_strdup(&c->vc_keymap, keymap) < 0 ||
- free_and_strdup(&c->vc_keymap_toggle, keymap_toggle) < 0)
- return -ENOMEM;
+ if (streq_ptr(keymap, c->vc_keymap) &&
+ streq_ptr(keymap_toggle, c->vc_keymap_toggle))
+ return sd_bus_reply_method_return(m, NULL);
- r = vconsole_write_data(c);
- if (r < 0) {
- log_error_errno(r, "Failed to set virtual console keymap: %m");
- return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %m");
- }
+ if ((keymap && (!filename_is_valid(keymap) || !string_is_safe(keymap))) ||
+ (keymap_toggle && (!filename_is_valid(keymap_toggle) || !string_is_safe(keymap_toggle))))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keymap data");
+
+ r = bus_verify_polkit_async(
+ m,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.locale1.set-keyboard",
+ NULL,
+ interactive,
+ UID_INVALID,
+ &polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ if (free_and_strdup(&c->vc_keymap, keymap) < 0 ||
+ free_and_strdup(&c->vc_keymap_toggle, keymap_toggle) < 0)
+ return -ENOMEM;
+
+ r = vconsole_write_data(c);
+ if (r < 0) {
+ log_error_errno(r, "Failed to set virtual console keymap: %m");
+ return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %m");
+ }
+
+ log_info("Changed virtual console keymap to '%s' toggle '%s'",
+ strempty(c->vc_keymap), strempty(c->vc_keymap_toggle));
- log_info("Changed virtual console keymap to '%s' toggle '%s'",
- strempty(c->vc_keymap), strempty(c->vc_keymap_toggle));
+ r = vconsole_reload(sd_bus_message_get_bus(m));
+ if (r < 0)
+ log_error_errno(r, "Failed to request keymap reload: %m");
- r = vconsole_reload(sd_bus_message_get_bus(m));
+ (void) sd_bus_emit_properties_changed(
+ sd_bus_message_get_bus(m),
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ "VConsoleKeymap", "VConsoleKeymapToggle", NULL);
+
+ if (convert) {
+ r = vconsole_convert_to_x11_and_emit(c, m);
if (r < 0)
- log_error_errno(r, "Failed to request keymap reload: %m");
-
- (void) sd_bus_emit_properties_changed(
- sd_bus_message_get_bus(m),
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "VConsoleKeymap", "VConsoleKeymapToggle", NULL);
-
- if (convert) {
- r = vconsole_convert_to_x11_and_emit(c, sd_bus_message_get_bus(m));
- if (r < 0)
- log_error_errno(r, "Failed to convert keymap data: %m");
- }
+ log_error_errno(r, "Failed to convert keymap data: %m");
}
return sd_bus_reply_method_return(m, NULL);
@@ -536,8 +581,7 @@ static int verify_xkb_rmlvo(const char *model, const char *layout, const char *v
static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Context *c = userdata;
const char *layout, *model, *variant, *options;
- int convert, interactive;
- int r;
+ int convert, interactive, r;
assert(m);
assert(c);
@@ -551,71 +595,77 @@ static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_err
variant = empty_to_null(variant);
options = empty_to_null(options);
- if (!streq_ptr(layout, c->x11_layout) ||
- !streq_ptr(model, c->x11_model) ||
- !streq_ptr(variant, c->x11_variant) ||
- !streq_ptr(options, c->x11_options)) {
-
- if ((layout && !string_is_safe(layout)) ||
- (model && !string_is_safe(model)) ||
- (variant && !string_is_safe(variant)) ||
- (options && !string_is_safe(options)))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keyboard data");
-
- r = bus_verify_polkit_async(
- m,
- CAP_SYS_ADMIN,
- "org.freedesktop.locale1.set-keyboard",
- NULL,
- interactive,
- UID_INVALID,
- &polkit_registry,
- error);
- if (r < 0)
- return r;
- if (r == 0)
- return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+ r = x11_read_data(c, m);
+ if (r < 0) {
+ log_error_errno(r, "Failed to read x11 keyboard layout data: %m");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to read x11 keyboard layout data");
+ }
- r = verify_xkb_rmlvo(model, layout, variant, options);
- if (r < 0) {
- log_error_errno(r, "Cannot compile XKB keymap for new x11 keyboard layout ('%s' / '%s' / '%s' / '%s'): %m",
- strempty(model), strempty(layout), strempty(variant), strempty(options));
+ if (streq_ptr(layout, c->x11_layout) &&
+ streq_ptr(model, c->x11_model) &&
+ streq_ptr(variant, c->x11_variant) &&
+ streq_ptr(options, c->x11_options))
+ return sd_bus_reply_method_return(m, NULL);
- if (r == -EOPNOTSUPP)
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Local keyboard configuration not supported on this system.");
+ if ((layout && !string_is_safe(layout)) ||
+ (model && !string_is_safe(model)) ||
+ (variant && !string_is_safe(variant)) ||
+ (options && !string_is_safe(options)))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keyboard data");
- return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Specified keymap cannot be compiled, refusing as invalid.");
- }
+ r = verify_xkb_rmlvo(model, layout, variant, options);
+ if (r < 0) {
+ log_error_errno(r, "Cannot compile XKB keymap for new x11 keyboard layout ('%s' / '%s' / '%s' / '%s'): %m",
+ strempty(model), strempty(layout), strempty(variant), strempty(options));
- if (free_and_strdup(&c->x11_layout, layout) < 0 ||
- free_and_strdup(&c->x11_model, model) < 0 ||
- free_and_strdup(&c->x11_variant, variant) < 0 ||
- free_and_strdup(&c->x11_options, options) < 0)
- return -ENOMEM;
+ if (r == -EOPNOTSUPP)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Local keyboard configuration not supported on this system.");
- r = x11_write_data(c);
- if (r < 0) {
- log_error_errno(r, "Failed to set X11 keyboard layout: %m");
- return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %m");
- }
+ return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Specified keymap cannot be compiled, refusing as invalid.");
+ }
- log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'",
- strempty(c->x11_layout),
- strempty(c->x11_model),
- strempty(c->x11_variant),
- strempty(c->x11_options));
-
- (void) sd_bus_emit_properties_changed(
- sd_bus_message_get_bus(m),
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "X11Layout", "X11Model", "X11Variant", "X11Options", NULL);
-
- if (convert) {
- r = x11_convert_to_vconsole_and_emit(c, sd_bus_message_get_bus(m));
- if (r < 0)
- log_error_errno(r, "Failed to convert keymap data: %m");
- }
+ r = bus_verify_polkit_async(
+ m,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.locale1.set-keyboard",
+ NULL,
+ interactive,
+ UID_INVALID,
+ &polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ if (free_and_strdup(&c->x11_layout, layout) < 0 ||
+ free_and_strdup(&c->x11_model, model) < 0 ||
+ free_and_strdup(&c->x11_variant, variant) < 0 ||
+ free_and_strdup(&c->x11_options, options) < 0)
+ return -ENOMEM;
+
+ r = x11_write_data(c);
+ if (r < 0) {
+ log_error_errno(r, "Failed to set X11 keyboard layout: %m");
+ return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %m");
+ }
+
+ log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'",
+ strempty(c->x11_layout),
+ strempty(c->x11_model),
+ strempty(c->x11_variant),
+ strempty(c->x11_options));
+
+ (void) sd_bus_emit_properties_changed(
+ sd_bus_message_get_bus(m),
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ "X11Layout", "X11Model", "X11Variant", "X11Options", NULL);
+
+ if (convert) {
+ r = x11_convert_to_vconsole_and_emit(c, m);
+ if (r < 0)
+ log_error_errno(r, "Failed to convert keymap data: %m");
}
return sd_bus_reply_method_return(m, NULL);
@@ -624,12 +674,12 @@ static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_err
static const sd_bus_vtable locale_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Locale", "as", property_get_locale, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("X11Layout", "s", NULL, offsetof(Context, x11_layout), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("X11Model", "s", NULL, offsetof(Context, x11_model), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("X11Variant", "s", NULL, offsetof(Context, x11_variant), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("X11Options", "s", NULL, offsetof(Context, x11_options), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("VConsoleKeymap", "s", NULL, offsetof(Context, vc_keymap), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("VConsoleKeymapToggle", "s", NULL, offsetof(Context, vc_keymap_toggle), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("X11Layout", "s", property_get_xkb, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("X11Model", "s", property_get_xkb, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("X11Variant", "s", property_get_xkb, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("X11Options", "s", property_get_xkb, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("VConsoleKeymap", "s", property_get_vconsole, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("VConsoleKeymapToggle", "s", property_get_vconsole, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_METHOD("SetLocale", "asb", NULL, method_set_locale, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetVConsoleKeyboard", "ssbb", NULL, method_set_vc_keyboard, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetX11Keyboard", "ssssbb", NULL, method_set_x11_keyboard, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -660,14 +710,17 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
- *_bus = bus;
- bus = NULL;
+ *_bus = TAKE_PTR(bus);
return 0;
}
int main(int argc, char *argv[]) {
- _cleanup_(context_free) Context context = {};
+ _cleanup_(context_free) Context context = {
+ .locale_mtime = USEC_INFINITY,
+ .vc_mtime = USEC_INFINITY,
+ .x11_mtime = USEC_INFINITY,
+ };
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
@@ -697,12 +750,6 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- r = context_read_data(&context);
- if (r < 0) {
- log_error_errno(r, "Failed to read locale data: %m");
- goto finish;
- }
-
r = bus_event_loop_with_idle(event, bus, "org.freedesktop.locale1", DEFAULT_EXIT_USEC, NULL, NULL);
if (r < 0)
log_error_errno(r, "Failed to run event loop: %m");
diff --git a/src/locale/meson.build b/src/locale/meson.build
index 6b85f6bea6..e87a10ebeb 100644
--- a/src/locale/meson.build
+++ b/src/locale/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
systemd_localed_sources = files('''
localed.c
diff --git a/src/locale/test-keymap-util.c b/src/locale/test-keymap-util.c
index fa26a0294e..e20731b253 100644
--- a/src/locale/test-keymap-util.c
+++ b/src/locale/test-keymap-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "keymap-util.h"
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
index c118421e6b..b0bb8de57e 100644
--- a/src/login/inhibit.c
+++ b/src/login/inhibit.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <getopt.h>
@@ -31,6 +13,7 @@
#include "bus-util.h"
#include "fd-util.h"
#include "format-util.h"
+#include "pager.h"
#include "process-util.h"
#include "signal-util.h"
#include "strv.h"
@@ -41,6 +24,7 @@ static const char* arg_what = "idle:sleep:shutdown";
static const char* arg_who = NULL;
static const char* arg_why = "Unknown reason";
static const char* arg_mode = NULL;
+static bool arg_no_pager = false;
static enum {
ACTION_INHIBIT,
@@ -82,6 +66,8 @@ static int print_inhibitors(sd_bus *bus, sd_bus_error *error) {
unsigned n = 0;
int r;
+ (void) pager_open(arg_no_pager, false);
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
@@ -134,6 +120,7 @@ static void help(void) {
"Execute a process while inhibiting shutdown/sleep/idle.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --no-pager Do not pipe output into a pager\n"
" --what=WHAT Operations to inhibit, colon separated list of:\n"
" shutdown, sleep, idle, handle-power-key,\n"
" handle-suspend-key, handle-hibernate-key,\n"
@@ -154,6 +141,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_WHY,
ARG_MODE,
ARG_LIST,
+ ARG_NO_PAGER,
};
static const struct option options[] = {
@@ -164,6 +152,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "why", required_argument, NULL, ARG_WHY },
{ "mode", required_argument, NULL, ARG_MODE },
{ "list", no_argument, NULL, ARG_LIST },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
@@ -203,6 +192,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_action = ACTION_LIST;
break;
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
case '?':
return -EINVAL;
@@ -244,6 +237,7 @@ int main(int argc, char *argv[]) {
if (arg_action == ACTION_LIST) {
r = print_inhibitors(bus, &error);
+ pager_close();
if (r < 0) {
log_error("Failed to list inhibitors: %s", bus_error_message(&error, -r));
return EXIT_FAILURE;
@@ -284,5 +278,5 @@ int main(int argc, char *argv[]) {
return r < 0 ? EXIT_FAILURE : r;
}
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index c811ee6c5e..be55fdbfd8 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
@@ -32,6 +14,7 @@
#include "bus-util.h"
#include "cgroup-show.h"
#include "cgroup-util.h"
+#include "format-table.h"
#include "log.h"
#include "logs-show.h"
#include "macro.h"
@@ -41,6 +24,7 @@
#include "sigbus.h"
#include "signal-util.h"
#include "spawn-polkit-agent.h"
+#include "string-table.h"
#include "strv.h"
#include "sysfs-show.h"
#include "terminal-util.h"
@@ -99,19 +83,45 @@ static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *e
return 0;
}
+static int show_table(Table *table, const char *word) {
+ int r;
+
+ assert(table);
+ assert(word);
+
+ if (table_get_rows(table) > 1) {
+ r = table_set_sort(table, (size_t) 0, (size_t) -1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to sort table: %m");
+
+ table_set_header(table, arg_legend);
+
+ r = table_print(table, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to show table: %m");
+ }
+
+ if (arg_legend) {
+ if (table_get_rows(table) > 1)
+ printf("\n%zu %s listed.\n", table_get_rows(table) - 1, word);
+ else
+ printf("No %s.\n", word);
+ }
+
+ return 0;
+}
+
static int list_sessions(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *id, *user, *seat, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
- uint32_t uid;
int r;
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -120,73 +130,79 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
"org.freedesktop.login1.Manager",
"ListSessions",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list sessions: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list sessions: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(susso)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%10s %10s %-16s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT", "TTY");
+ table = table_new("SESSION", "UID", "USER", "SEAT", "TTY");
+ if (!table)
+ return log_oom();
+
+ /* Right-align the first two fields (since they are numeric) */
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100);
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(1), 100);
- while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
- _cleanup_(sd_bus_error_free) sd_bus_error error2 = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply2 = NULL;
- _cleanup_free_ char *path = NULL;
- const char *tty = NULL;
+ for (;;) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_tty = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_tty = NULL;
+ const char *id, *user, *seat, *object, *tty = NULL;
+ uint32_t uid;
+
+ r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
- r = get_session_path(bus, id, &error2, &path);
+ r = sd_bus_get_property(
+ bus,
+ "org.freedesktop.login1",
+ object,
+ "org.freedesktop.login1.Session",
+ "TTY",
+ &error_tty,
+ &reply_tty,
+ "s");
if (r < 0)
- log_warning("Failed to get session path: %s", bus_error_message(&error, r));
+ log_warning_errno(r, "Failed to get TTY for session %s: %s", id, bus_error_message(&error_tty, r));
else {
- r = sd_bus_get_property(
- bus,
- "org.freedesktop.login1",
- path,
- "org.freedesktop.login1.Session",
- "TTY",
- &error2,
- &reply2,
- "s");
+ r = sd_bus_message_read(reply_tty, "s", &tty);
if (r < 0)
- log_warning("Failed to get TTY for session %s: %s",
- id, bus_error_message(&error2, r));
- else {
- r = sd_bus_message_read(reply2, "s", &tty);
- if (r < 0)
- return bus_log_parse_error(r);
- }
+ return bus_log_parse_error(r);
}
- printf("%10s %10"PRIu32" %-16s %-16s %-16s\n", id, uid, user, seat, strna(tty));
- k++;
+ r = table_add_many(table,
+ TABLE_STRING, id,
+ TABLE_UINT32, uid,
+ TABLE_STRING, user,
+ TABLE_STRING, seat,
+ TABLE_STRING, strna(tty));
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u sessions listed.\n", k);
-
- return 0;
+ return show_table(table, "sessions");
}
static int list_users(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *user, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
- uint32_t uid;
int r;
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -195,43 +211,55 @@ static int list_users(int argc, char *argv[], void *userdata) {
"org.freedesktop.login1.Manager",
"ListUsers",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list users: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list users: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(uso)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%10s %-16s\n", "UID", "USER");
+ table = table_new("UID", "USER");
+ if (!table)
+ return log_oom();
+
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100);
+
+ for (;;) {
+ const char *user;
+ uint32_t uid;
- while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
- printf("%10"PRIu32" %-16s\n", uid, user);
- k++;
+ r = sd_bus_message_read(reply, "(uso)", &uid, &user, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ r = table_add_many(table,
+ TABLE_UINT32, uid,
+ TABLE_STRING, user);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u users listed.\n", k);
-
- return 0;
+ return show_table(table, "users");
}
static int list_seats(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *seat, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
int r;
+
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -240,30 +268,37 @@ static int list_seats(int argc, char *argv[], void *userdata) {
"org.freedesktop.login1.Manager",
"ListSeats",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list seats: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list seats: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(so)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%-16s\n", "SEAT");
+ table = table_new("SEAT");
+ if (!table)
+ return log_oom();
+
+ for (;;) {
+ const char *seat;
- while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
- printf("%-16s\n", seat);
- k++;
+ r = sd_bus_message_read(reply, "(so)", &seat, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ r = table_add_cell(table, NULL, TABLE_STRING, seat);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u seats listed.\n", k);
-
- return 0;
+ return show_table(table, "seats");
}
static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) {
@@ -307,77 +342,52 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
}
typedef struct SessionStatusInfo {
- char *id;
+ const char *id;
uid_t uid;
- char *name;
+ const char *name;
struct dual_timestamp timestamp;
unsigned int vtnr;
- char *seat;
- char *tty;
- char *display;
- int remote;
- char *remote_host;
- char *remote_user;
- char *service;
+ const char *seat;
+ const char *tty;
+ const char *display;
+ bool remote;
+ const char *remote_host;
+ const char *remote_user;
+ const char *service;
pid_t leader;
- char *type;
- char *class;
- char *state;
- char *scope;
- char *desktop;
+ const char *type;
+ const char *class;
+ const char *state;
+ const char *scope;
+ const char *desktop;
} SessionStatusInfo;
typedef struct UserStatusInfo {
uid_t uid;
- int linger;
- char *name;
+ bool linger;
+ const char *name;
struct dual_timestamp timestamp;
- char *state;
+ const char *state;
char **sessions;
- char *display;
- char *slice;
+ const char *display;
+ const char *slice;
} UserStatusInfo;
typedef struct SeatStatusInfo {
- char *id;
- char *active_session;
+ const char *id;
+ const char *active_session;
char **sessions;
} SeatStatusInfo;
-static void session_status_info_clear(SessionStatusInfo *info) {
- if (info) {
- free(info->id);
- free(info->name);
- free(info->seat);
- free(info->tty);
- free(info->display);
- free(info->remote_host);
- free(info->remote_user);
- free(info->service);
- free(info->type);
- free(info->class);
- free(info->state);
- free(info->scope);
- free(info->desktop);
- zero(*info);
- }
-}
-
static void user_status_info_clear(UserStatusInfo *info) {
if (info) {
- free(info->name);
- free(info->state);
strv_free(info->sessions);
- free(info->display);
- free(info->slice);
zero(*info);
}
}
static void seat_status_info_clear(SeatStatusInfo *info) {
if (info) {
- free(info->id);
- free(info->active_session);
strv_free(info->sessions);
zero(*info);
}
@@ -395,22 +405,9 @@ static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_mess
if (r < 0)
return r;
- if (IN_SET(contents[0], 's', 'o')) {
- const char *s;
- char **p = (char **) userdata;
-
- r = sd_bus_message_read_basic(m, contents[0], &s);
- if (r < 0)
- return r;
-
- r = free_and_strdup(p, s);
- if (r < 0)
- return r;
- } else {
- r = sd_bus_message_read_basic(m, contents[0], userdata);
- if (r < 0)
- return r;
- }
+ r = sd_bus_message_read_basic(m, contents[0], userdata);
+ if (r < 0)
+ return r;
r = sd_bus_message_skip(m, contents+1);
if (r < 0)
@@ -471,12 +468,14 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
- _cleanup_(session_status_info_clear) SessionStatusInfo i = {};
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2;
+ SessionStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -601,12 +600,14 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2;
_cleanup_(user_status_info_clear) UserStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -676,10 +677,11 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, 0, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -723,40 +725,41 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
#define property(name, fmt, ...) \
do { \
- if (arg_value) \
+ if (value) \
printf(fmt "\n", __VA_ARGS__); \
else \
printf("%s=" fmt "\n", name, __VA_ARGS__); \
} while (0)
-static int print_property(const char *name, sd_bus_message *m, const char *contents) {
+static int print_property(const char *name, sd_bus_message *m, bool value, bool all) {
+ char type;
+ const char *contents;
int r;
assert(name);
assert(m);
- assert(contents);
- if (arg_property && !strv_find(arg_property, name))
- /* skip what we didn't read */
- return sd_bus_message_skip(m, contents);
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
- switch (contents[0]) {
+ switch (type) {
- case SD_BUS_TYPE_STRUCT_BEGIN:
+ case SD_BUS_TYPE_STRUCT:
- if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
+ if (contents[0] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
const char *s;
r = sd_bus_message_read(m, "(so)", &s, NULL);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || !isempty(s))
+ if (all || !isempty(s))
property(name, "%s", s);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
+ } else if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
uint32_t uid;
r = sd_bus_message_read(m, "(uo)", &uid, NULL);
@@ -769,14 +772,13 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
}
property(name, UID_FMT, uid);
- return 0;
+ return 1;
}
-
break;
case SD_BUS_TYPE_ARRAY:
- if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
+ if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
const char *s;
bool space = false;
@@ -784,7 +786,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- if (!arg_value)
+ if (!value)
printf("%s=", name);
while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
@@ -792,7 +794,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
space = true;
}
- if (space || !arg_value)
+ if (space || !value)
printf("\n");
if (r < 0)
@@ -802,89 +804,27 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
}
-
break;
}
- r = bus_print_property(name, m, arg_value, arg_all);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (r == 0) {
- r = sd_bus_message_skip(m, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (arg_all)
- printf("%s=[unprintable]\n", name);
- }
-
return 0;
}
static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
assert(path);
assert(new_line);
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.login1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &error,
- &reply,
- "s", "");
- if (r < 0)
- return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
if (*new_line)
printf("\n");
*new_line = true;
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *name, *contents;
-
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_peek_type(reply, NULL, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = print_property(name, reply, contents);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
+ r = bus_print_all_properties(bus, "org.freedesktop.login1", path, print_property, arg_property, arg_value, arg_all, NULL);
if (r < 0)
return bus_log_parse_error(r);
@@ -903,7 +843,7 @@ static int show_session(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
const char *session, *p = "/org/freedesktop/login1/session/self";
@@ -955,7 +895,7 @@ static int show_user(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -1015,7 +955,7 @@ static int show_seat(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -1499,6 +1439,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
@@ -1523,7 +1468,12 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 's':
- arg_signal = signal_from_string_try_harder(optarg);
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
+ arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
return -EINVAL;
diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
index 3f355e7ea8..cafeb8822f 100644
--- a/src/login/logind-acl.c
+++ b/src/login/logind-acl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -181,7 +163,7 @@ int devnode_acl_all(struct udev *udev,
bool del, uid_t old_uid,
bool add, uid_t new_uid) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
_cleanup_set_free_free_ Set *nodes = NULL;
_cleanup_closedir_ DIR *dir = NULL;
@@ -222,7 +204,7 @@ int devnode_acl_all(struct udev *udev,
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
const char *node, *sn;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
diff --git a/src/login/logind-acl.h b/src/login/logind-acl.h
index 36690dabd3..79700670cc 100644
--- a/src/login/logind-acl.h
+++ b/src/login/logind-acl.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index 852ea9f949..08e41af81a 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
@@ -33,6 +15,24 @@
#include "terminal-util.h"
#include "user-util.h"
+const char* manager_target_for_action(HandleAction handle) {
+ static const char * const target_table[_HANDLE_ACTION_MAX] = {
+ [HANDLE_POWEROFF] = SPECIAL_POWEROFF_TARGET,
+ [HANDLE_REBOOT] = SPECIAL_REBOOT_TARGET,
+ [HANDLE_HALT] = SPECIAL_HALT_TARGET,
+ [HANDLE_KEXEC] = SPECIAL_KEXEC_TARGET,
+ [HANDLE_SUSPEND] = SPECIAL_SUSPEND_TARGET,
+ [HANDLE_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
+ [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET,
+ [HANDLE_SUSPEND_THEN_HIBERNATE] = SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
+ };
+
+ assert(handle >= 0);
+ if (handle < (ssize_t) ELEMENTSOF(target_table))
+ return target_table[handle];
+ return NULL;
+}
+
int manager_handle_action(
Manager *m,
InhibitWhat inhibit_key,
@@ -47,23 +47,15 @@ int manager_handle_action(
[HANDLE_KEXEC] = "Rebooting via kexec...",
[HANDLE_SUSPEND] = "Suspending...",
[HANDLE_HIBERNATE] = "Hibernating...",
- [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending..."
- };
-
- static const char * const target_table[_HANDLE_ACTION_MAX] = {
- [HANDLE_POWEROFF] = SPECIAL_POWEROFF_TARGET,
- [HANDLE_REBOOT] = SPECIAL_REBOOT_TARGET,
- [HANDLE_HALT] = SPECIAL_HALT_TARGET,
- [HANDLE_KEXEC] = SPECIAL_KEXEC_TARGET,
- [HANDLE_SUSPEND] = SPECIAL_SUSPEND_TARGET,
- [HANDLE_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
- [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
+ [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending...",
+ [HANDLE_SUSPEND_THEN_HIBERNATE] = "Suspending, then hibernating...",
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
InhibitWhat inhibit_operation;
Inhibitor *offending = NULL;
bool supported;
+ const char *target;
int r;
assert(m);
@@ -95,7 +87,6 @@ int manager_handle_action(
/* Locking is handled differently from the rest. */
if (handle == HANDLE_LOCK) {
-
if (!is_edge)
return 0;
@@ -110,6 +101,8 @@ int manager_handle_action(
supported = can_sleep("hibernate") > 0;
else if (handle == HANDLE_HYBRID_SLEEP)
supported = can_sleep("hybrid-sleep") > 0;
+ else if (handle == HANDLE_SUSPEND_THEN_HIBERNATE)
+ supported = can_sleep("suspend-then-hibernate") > 0;
else if (handle == HANDLE_KEXEC)
supported = access(KEXEC, X_OK) >= 0;
else
@@ -125,7 +118,11 @@ int manager_handle_action(
return -EALREADY;
}
- inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
+ assert_se(target = manager_target_for_action(handle));
+
+ inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE,
+ HANDLE_HYBRID_SLEEP,
+ HANDLE_SUSPEND_THEN_HIBERNATE) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
/* If the actual operation is inhibited, warn and fail */
if (!ignore_inhibited &&
@@ -154,7 +151,7 @@ int manager_handle_action(
log_info("%s", message_table[handle]);
- r = bus_manager_shutdown_or_sleep_now_or_later(m, target_table[handle], inhibit_operation, &error);
+ r = bus_manager_shutdown_or_sleep_now_or_later(m, target, inhibit_operation, &error);
if (r < 0) {
log_error("Failed to execute operation: %s", bus_error_message(&error, r));
return r;
@@ -172,7 +169,8 @@ static const char* const handle_action_table[_HANDLE_ACTION_MAX] = {
[HANDLE_SUSPEND] = "suspend",
[HANDLE_HIBERNATE] = "hibernate",
[HANDLE_HYBRID_SLEEP] = "hybrid-sleep",
- [HANDLE_LOCK] = "lock"
+ [HANDLE_SUSPEND_THEN_HIBERNATE] = "suspend-then-hibernate",
+ [HANDLE_LOCK] = "lock",
};
DEFINE_STRING_TABLE_LOOKUP(handle_action, HandleAction);
diff --git a/src/login/logind-action.h b/src/login/logind-action.h
index 8c31ec42be..a45aab7854 100644
--- a/src/login/logind-action.h
+++ b/src/login/logind-action.h
@@ -1,24 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "conf-parser.h"
typedef enum HandleAction {
HANDLE_IGNORE,
@@ -29,6 +12,7 @@ typedef enum HandleAction {
HANDLE_SUSPEND,
HANDLE_HIBERNATE,
HANDLE_HYBRID_SLEEP,
+ HANDLE_SUSPEND_THEN_HIBERNATE,
HANDLE_LOCK,
_HANDLE_ACTION_MAX,
_HANDLE_ACTION_INVALID = -1
@@ -47,4 +31,6 @@ int manager_handle_action(
const char* handle_action_to_string(HandleAction h) _const_;
HandleAction handle_action_from_string(const char *s) _pure_;
-int config_parse_handle_action(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+const char* manager_target_for_action(HandleAction handle);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_handle_action);
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index 2da6e69952..0defa6b9ba 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -172,8 +154,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_POWER2:
log_struct(LOG_INFO,
LOG_MESSAGE("Power key pressed."),
- "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
break;
@@ -187,8 +168,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_SLEEP:
log_struct(LOG_INFO,
LOG_MESSAGE("Suspend key pressed."),
- "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true);
break;
@@ -196,8 +176,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_SUSPEND:
log_struct(LOG_INFO,
LOG_MESSAGE("Hibernate key pressed."),
- "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true);
break;
@@ -208,8 +187,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
if (ev.code == SW_LID) {
log_struct(LOG_INFO,
LOG_MESSAGE("Lid closed."),
- "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR);
b->lid_closed = true;
button_lid_switch_handle_action(b->manager, true);
@@ -218,8 +196,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
} else if (ev.code == SW_DOCK) {
log_struct(LOG_INFO,
LOG_MESSAGE("System docked."),
- "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR);
b->docked = true;
}
@@ -229,8 +206,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
if (ev.code == SW_LID) {
log_struct(LOG_INFO,
LOG_MESSAGE("Lid opened."),
- "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR);
b->lid_closed = false;
b->check_event_source = sd_event_source_unref(b->check_event_source);
@@ -238,8 +214,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
} else if (ev.code == SW_DOCK) {
log_struct(LOG_INFO,
LOG_MESSAGE("System undocked."),
- "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR);
b->docked = false;
}
diff --git a/src/login/logind-button.h b/src/login/logind-button.h
index b47eb47571..740cf0b786 100644
--- a/src/login/logind-button.h
+++ b/src/login/logind-button.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Button Button;
#include "logind.h"
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index 41b4d4d8d7..dbae4bf5af 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <pwd.h>
@@ -28,6 +10,7 @@
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-util.h"
+#include "conf-parser.h"
#include "fd-util.h"
#include "logind.h"
#include "parse-util.h"
@@ -37,6 +20,50 @@
#include "udev-util.h"
#include "user-util.h"
+void manager_reset_config(Manager *m) {
+ assert(m);
+
+ m->n_autovts = 6;
+ m->reserve_vt = 6;
+ m->remove_ipc = true;
+ m->inhibit_delay_max = 5 * USEC_PER_SEC;
+ m->handle_power_key = HANDLE_POWEROFF;
+ m->handle_suspend_key = HANDLE_SUSPEND;
+ m->handle_hibernate_key = HANDLE_HIBERNATE;
+ m->handle_lid_switch = HANDLE_SUSPEND;
+ m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
+ m->handle_lid_switch_docked = HANDLE_IGNORE;
+ m->power_key_ignore_inhibited = false;
+ m->suspend_key_ignore_inhibited = false;
+ m->hibernate_key_ignore_inhibited = false;
+ m->lid_switch_ignore_inhibited = true;
+
+ m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
+
+ m->idle_action_usec = 30 * USEC_PER_MINUTE;
+ m->idle_action = HANDLE_IGNORE;
+
+ m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
+ m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
+ m->sessions_max = 8192;
+ m->inhibitors_max = 8192;
+
+ m->kill_user_processes = KILL_USER_PROCESSES;
+
+ m->kill_only_users = strv_free(m->kill_only_users);
+ m->kill_exclude_users = strv_free(m->kill_exclude_users);
+}
+
+int manager_parse_config_file(Manager *m) {
+ assert(m);
+
+ return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
+ CONF_PATHS_NULSTR("systemd/logind.conf.d"),
+ "Login\0",
+ config_item_perf_lookup, logind_gperf_lookup,
+ CONFIG_PARSE_WARN, m);
+}
+
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
Device *d;
@@ -282,7 +309,7 @@ int manager_process_button_device(Manager *m, struct udev_device *d) {
return 0;
}
-int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
+int manager_get_session_by_pid(Manager *m, pid_t pid, Session **ret) {
_cleanup_free_ char *unit = NULL;
Session *s;
int r;
@@ -294,38 +321,51 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
r = cg_pid_get_unit(pid, &unit);
if (r < 0)
- return 0;
+ goto not_found;
s = hashmap_get(m->session_units, unit);
if (!s)
- return 0;
+ goto not_found;
+
+ if (ret)
+ *ret = s;
- if (session)
- *session = s;
return 1;
+
+not_found:
+ if (ret)
+ *ret = NULL;
+ return 0;
}
-int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
+int manager_get_user_by_pid(Manager *m, pid_t pid, User **ret) {
_cleanup_free_ char *unit = NULL;
User *u;
int r;
assert(m);
- assert(user);
if (!pid_is_valid(pid))
return -EINVAL;
r = cg_pid_get_slice(pid, &unit);
if (r < 0)
- return 0;
+ goto not_found;
u = hashmap_get(m->user_units, unit);
if (!u)
- return 0;
+ goto not_found;
+
+ if (ret)
+ *ret = u;
- *user = u;
return 1;
+
+not_found:
+ if (ret)
+ *ret = NULL;
+
+ return 0;
}
int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
@@ -499,7 +539,7 @@ static bool manager_is_docked(Manager *m) {
}
static int manager_count_external_displays(Manager *m) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
int n = 0;
@@ -518,7 +558,7 @@ static int manager_count_external_displays(Manager *m) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
struct udev_device *p;
const char *status, *enabled, *dash, *nn, *i;
bool external = false;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 4a85d751bc..13298cc855 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <pwd.h>
@@ -29,6 +11,7 @@
#include "audit-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
+#include "bus-unit-util.h"
#include "bus-util.h"
#include "dirent-util.h"
#include "efivars.h"
@@ -254,9 +237,9 @@ static int property_get_preparing(
assert(m);
if (streq(property, "PreparingForShutdown"))
- b = !!(m->action_what & INHIBIT_SHUTDOWN);
+ b = m->action_what & INHIBIT_SHUTDOWN;
else
- b = !!(m->action_what & INHIBIT_SLEEP);
+ b = m->action_what & INHIBIT_SLEEP;
return sd_bus_message_append(reply, "b", b);
}
@@ -289,60 +272,9 @@ static int property_get_scheduled_shutdown(
}
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
-
-static int property_get_docked(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
-}
-
-static int property_get_current_sessions(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
-}
-
-static int property_get_current_inhibitors(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
-}
+static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size);
static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
@@ -658,10 +590,9 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu
static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
- uint32_t audit_id = 0;
- _cleanup_free_ char *unit = NULL;
_cleanup_free_ char *id = NULL;
Session *session = NULL;
+ uint32_t audit_id = 0;
Manager *m = userdata;
User *user = NULL;
Seat *seat = NULL;
@@ -685,7 +616,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (!uid_is_valid(uid))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
- if (leader < 0 || leader == 1)
+ if (leader < 0 || leader == 1 || leader == getpid_cached())
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
if (isempty(type))
@@ -731,7 +662,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (v <= 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
- if (!vtnr)
+ if (vtnr == 0)
vtnr = (uint32_t) v;
else if (vtnr != (uint32_t) v)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
@@ -749,7 +680,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (seat) {
if (seat_has_vts(seat)) {
- if (!vtnr || vtnr > 63)
+ if (vtnr <= 0 || vtnr > 63)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
} else {
if (vtnr != 0)
@@ -757,10 +688,6 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
}
}
- r = sd_bus_message_enter_container(message, 'a', "(sv)");
- if (r < 0)
- return r;
-
if (t == _SESSION_TYPE_INVALID) {
if (!isempty(display))
t = SESSION_X11;
@@ -789,16 +716,13 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
return r;
}
- /*
- * Check if we are already in a logind session. Or if we are in user@.service
- * which is a special PAM session that avoids creating a logind session.
- */
- r = cg_pid_get_unit(leader, &unit);
+ /* Check if we are already in a logind session. Or if we are in user@.service which is a special PAM session
+ * that avoids creating a logind session. */
+ r = manager_get_user_by_pid(m, leader, NULL);
if (r < 0)
return r;
- if (hashmap_get(m->session_units, unit) ||
- hashmap_get(m->user_units, unit))
- return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
+ if (r > 0)
+ return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session or user slice");
/*
* Old gdm and lightdm start the user-session on the same VT as
@@ -832,9 +756,8 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
* the audit data and let's better register a new
* ID */
if (hashmap_get(m->sessions, id)) {
- log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
+ log_warning("Existing logind session ID %s used by new audit session, ignoring.", id);
audit_id = AUDIT_SESSION_INVALID;
-
id = mfree(id);
}
}
@@ -920,14 +843,21 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
goto fail;
}
- r = session_start(session);
+ r = sd_bus_message_enter_container(message, 'a', "(sv)");
+ if (r < 0)
+ return r;
+
+ r = session_start(session, message);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_message_exit_container(message);
if (r < 0)
goto fail;
session->create_message = sd_bus_message_ref(message);
- /* Now, let's wait until the slice unit and stuff got
- * created. We send the reply back from
+ /* Now, let's wait until the slice unit and stuff got created. We send the reply back from
* session_send_create_reply(). */
return 1;
@@ -1225,7 +1155,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
mkdir_p_label("/var/lib/systemd", 0755);
- r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, false);
+ r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
return r;
@@ -1260,7 +1190,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
}
static int trigger_device(Manager *m, struct udev_device *d) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *first, *item;
int r;
@@ -1298,7 +1228,7 @@ static int trigger_device(Manager *m, struct udev_device *d) {
}
static int attach_device(Manager *m, const char *seat, const char *sysfs) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
_cleanup_free_ char *rule = NULL, *file = NULL;
const char *id_for_seat;
int r;
@@ -1486,8 +1416,7 @@ static int bus_manager_log_shutdown(
return log_struct(LOG_NOTICE,
"MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
p,
- q,
- NULL);
+ q);
}
static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
@@ -1711,6 +1640,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(
InhibitWhat w,
sd_bus_error *error) {
+ _cleanup_free_ char *load_state = NULL;
bool delayed;
int r;
@@ -1720,6 +1650,15 @@ int bus_manager_shutdown_or_sleep_now_or_later(
assert(w <= _INHIBIT_WHAT_MAX);
assert(!m->action_job);
+ r = unit_load_state(m->bus, unit_name, &load_state);
+ if (r < 0)
+ return r;
+
+ if (!streq(load_state, "loaded")) {
+ log_notice("Unit %s is %s, refusing operation.", unit_name, load_state);
+ return -EACCES;
+ }
+
/* Tell everybody to prepare for shutdown/sleep */
(void) send_prepare_for(m, w, true);
@@ -1830,11 +1769,14 @@ static int method_do_shutdown_or_sleep(
if (sleep_verb) {
r = can_sleep(sleep_verb);
+ if (r == -ENOSPC)
+ return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
+ "Not enough swap space for hibernation");
+ if (r == 0)
+ return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
+ "Sleep verb \"%s\" not supported", sleep_verb);
if (r < 0)
return r;
-
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
}
r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
@@ -1933,6 +1875,20 @@ static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_e
error);
}
+static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ return method_do_shutdown_or_sleep(
+ m, message,
+ SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.hibernate",
+ "org.freedesktop.login1.hibernate-multiple-sessions",
+ "org.freedesktop.login1.hibernate-ignore-inhibit",
+ "hybrid-sleep",
+ error);
+}
+
static int nologin_timeout_handler(
sd_event_source *s,
uint64_t usec,
@@ -1955,7 +1911,7 @@ static int update_schedule_file(Manager *m) {
assert(m);
- r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, false);
+ r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
@@ -2227,6 +2183,7 @@ static int method_can_shutdown_or_sleep(
sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ HandleAction handle;
bool multiple_sessions, challenge, blocked;
const char *result = NULL;
uid_t uid;
@@ -2242,10 +2199,10 @@ static int method_can_shutdown_or_sleep(
if (sleep_verb) {
r = can_sleep(sleep_verb);
+ if (IN_SET(r, 0, -ENOSPC))
+ return sd_bus_reply_method_return(message, "s", "na");
if (r < 0)
return r;
- if (r == 0)
- return sd_bus_reply_method_return(message, "s", "na");
}
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
@@ -2263,6 +2220,25 @@ static int method_can_shutdown_or_sleep(
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
+ handle = handle_action_from_string(sleep_verb);
+ if (handle >= 0) {
+ const char *target;
+
+ target = manager_target_for_action(handle);
+ if (target) {
+ _cleanup_free_ char *load_state = NULL;
+
+ r = unit_load_state(m->bus, target, &load_state);
+ if (r < 0)
+ return r;
+
+ if (!streq(load_state, "loaded")) {
+ result = "no";
+ goto finish;
+ }
+ }
+ }
+
if (multiple_sessions) {
r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
if (r < 0)
@@ -2305,6 +2281,7 @@ static int method_can_shutdown_or_sleep(
result = "no";
}
+ finish:
return sd_bus_reply_method_return(message, "s", result);
}
@@ -2386,6 +2363,19 @@ static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_b
error);
}
+static int method_can_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ return method_can_shutdown_or_sleep(
+ m, message,
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.hibernate",
+ "org.freedesktop.login1.hibernate-multiple-sessions",
+ "org.freedesktop.login1.hibernate-ignore-inhibit",
+ "suspend-then-hibernate",
+ error);
+}
+
static int property_get_reboot_to_firmware_setup(
sd_bus *bus,
const char *path,
@@ -2491,7 +2481,7 @@ static int method_set_wall_message(
int r;
Manager *m = userdata;
char *wall_message;
- int enable_wall_messages;
+ unsigned enable_wall_messages;
assert(message);
assert(m);
@@ -2668,12 +2658,12 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
+ SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), 0),
SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
- SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
+ SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2706,12 +2696,14 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2931,78 +2923,6 @@ static int strdup_job(sd_bus_message *reply, char **job) {
return 1;
}
-int manager_start_slice(
- Manager *manager,
- const char *slice,
- const char *description,
- const char *after,
- const char *after2,
- uint64_t tasks_max,
- sd_bus_error *error,
- char **job) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
- int r;
-
- assert(manager);
- assert(slice);
- assert(job);
-
- r = sd_bus_message_new_method_call(
- manager->bus,
- &m,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "StartTransientUnit");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, 'a', "(sv)");
- if (r < 0)
- return r;
-
- if (!isempty(description)) {
- r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
- if (r < 0)
- return r;
- }
-
- if (!isempty(after)) {
- r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
- if (r < 0)
- return r;
- }
-
- if (!isempty(after2)) {
- r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "a(sa(sv))", 0);
- if (r < 0)
- return r;
-
- r = sd_bus_call(manager->bus, m, 0, error, &reply);
- if (r < 0)
- return r;
-
- return strdup_job(reply, job);
-}
-
int manager_start_scope(
Manager *manager,
const char *scope,
@@ -3011,7 +2931,7 @@ int manager_start_scope(
const char *description,
const char *after,
const char *after2,
- uint64_t tasks_max,
+ sd_bus_message *more_properties,
sd_bus_error *error,
char **job) {
@@ -3065,13 +2985,8 @@ int manager_start_scope(
return r;
}
- /* cgroup empty notification is not available in containers
- * currently. To make this less problematic, let's shorten the
- * stop timeout for sessions, so that we don't wait
- * forever. */
-
- /* Make sure that the session shells are terminated with
- * SIGHUP since bash and friends tend to ignore SIGTERM */
+ /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
+ * SIGTERM */
r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
if (r < 0)
return r;
@@ -3080,9 +2995,17 @@ int manager_start_scope(
if (r < 0)
return r;
- r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
+ /* disable TasksMax= for the session scope, rely on the slice setting for it */
+ r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", (uint64_t)-1);
if (r < 0)
- return r;
+ return bus_log_create_error(r);
+
+ if (more_properties) {
+ /* If TasksMax also appears here, it will overwrite the default value set above */
+ r = sd_bus_message_copy(m, more_properties, true);
+ if (r < 0)
+ return r;
+ }
r = sd_bus_message_close_container(m);
if (r < 0)
diff --git a/src/login/logind-device.c b/src/login/logind-device.c
index 758ba73c2b..9b5b3e8798 100644
--- a/src/login/logind-device.c
+++ b/src/login/logind-device.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
diff --git a/src/login/logind-device.h b/src/login/logind-device.h
index d0911560dd..cc6e523675 100644
--- a/src/login/logind-device.h
+++ b/src/login/logind-device.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Device Device;
#include "list.h"
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index f6f57526f6..c85339dcd3 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -17,27 +17,27 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Login.NAutoVTs, config_parse_n_autovts, 0, offsetof(Manager, n_autovts)
-Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt)
-Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes)
-Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users)
-Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users)
-Login.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max)
-Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key)
-Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key)
-Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key)
-Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch)
-Login.HandleLidSwitchExternalPower,config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep)
-Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked)
-Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited)
-Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited)
-Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited)
-Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited)
-Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec)
-Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action)
-Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec)
-Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size)
-Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc)
-Login.InhibitorsMax, config_parse_uint64, 0, offsetof(Manager, inhibitors_max)
-Login.SessionsMax, config_parse_uint64, 0, offsetof(Manager, sessions_max)
-Login.UserTasksMax, config_parse_user_tasks_max,0, offsetof(Manager, user_tasks_max)
+Login.NAutoVTs, config_parse_n_autovts, 0, offsetof(Manager, n_autovts)
+Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt)
+Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes)
+Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users)
+Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users)
+Login.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max)
+Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key)
+Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key)
+Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key)
+Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch)
+Login.HandleLidSwitchExternalPower, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep)
+Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked)
+Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited)
+Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited)
+Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited)
+Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited)
+Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec)
+Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action)
+Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec)
+Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size)
+Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc)
+Login.InhibitorsMax, config_parse_uint64, 0, offsetof(Manager, inhibitors_max)
+Login.SessionsMax, config_parse_uint64, 0, offsetof(Manager, sessions_max)
+Login.UserTasksMax, config_parse_compat_user_tasks_max, 0, offsetof(Manager, user_tasks_max)
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index e14835292e..b1f45baaca 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -87,7 +69,7 @@ int inhibitor_save(Inhibitor *i) {
assert(i);
- r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, false);
+ r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -211,7 +193,7 @@ int inhibitor_load(Inhibitor *i) {
char *cc;
int r;
- r = parse_env_file(i->state_file, NEWLINE,
+ r = parse_env_file(NULL, i->state_file, NEWLINE,
"WHAT", &what,
"UID", &uid,
"PID", &pid,
@@ -291,7 +273,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
/* Create FIFO */
if (!i->fifo_path) {
- r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, false);
+ r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
return r;
diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h
index cc6c62ab18..d358a48559 100644
--- a/src/login/logind-inhibit.h
+++ b/src/login/logind-inhibit.h
@@ -1,28 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Inhibitor Inhibitor;
-
typedef enum InhibitWhat {
INHIBIT_SHUTDOWN = 1,
INHIBIT_SLEEP = 2,
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index 8e4e4efc81..c4d9b067c6 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -31,6 +13,10 @@
#include "user-util.h"
#include "util.h"
+static BUS_DEFINE_PROPERTY_GET(property_get_can_multi_session, "b", Seat, seat_can_multi_session);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_tty, "b", Seat, seat_can_tty);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_graphical, "b", Seat, seat_can_graphical);
+
static int property_get_active_session(
sd_bus *bus,
const char *path,
@@ -54,60 +40,6 @@ static int property_get_active_session(
return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
}
-static int property_get_can_multi_session(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
-}
-
-static int property_get_can_tty(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_tty(s));
-}
-
-static int property_get_can_graphical(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_graphical(s));
-}
-
static int property_get_sessions(
sd_bus *bus,
const char *path,
@@ -419,8 +351,7 @@ int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
}
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 46e7c06ddc..63253db5bf 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -95,7 +77,7 @@ int seat_save(Seat *s) {
if (!s->started)
return 0;
- r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0, false);
+ r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -420,8 +402,7 @@ int seat_start(Seat *s) {
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SEAT_START_STR,
"SEAT_ID=%s", s->id,
- LOG_MESSAGE("New seat %s.", s->id),
- NULL);
+ LOG_MESSAGE("New seat %s.", s->id));
/* Initialize VT magic stuff */
seat_preallocate_vts(s);
@@ -448,8 +429,7 @@ int seat_stop(Seat *s, bool force) {
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SEAT_STOP_STR,
"SEAT_ID=%s", s->id,
- LOG_MESSAGE("Removed seat %s.", s->id),
- NULL);
+ LOG_MESSAGE("Removed seat %s.", s->id));
seat_stop_sessions(s, force);
@@ -560,8 +540,7 @@ void seat_complete_switch(Seat *s) {
if (!s->pending_switch)
return;
- session = s->pending_switch;
- s->pending_switch = NULL;
+ session = TAKE_PTR(s->pending_switch);
seat_set_active(s, session);
}
diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h
index 4982ea3381..70878bbe52 100644
--- a/src/login/logind-seat.h
+++ b/src/login/logind-seat.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Seat Seat;
#include "list.h"
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index 8264a42fd4..25c4981dc0 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -99,42 +81,8 @@ static int property_get_seat(
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
-
-static int property_get_active(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Session *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", session_is_active(s));
-}
-
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Session *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "s", session_state_to_string(session_get_state(s)));
-}
+static BUS_DEFINE_PROPERTY_GET(property_get_active, "b", Session, session_is_active);
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Session, session_get_state, session_state_to_string);
static int property_get_idle_hint(
sd_bus *bus,
@@ -666,8 +614,7 @@ int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
}
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 73eee72515..c2dfe9f974 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 <fcntl.h>
#include <linux/input.h>
@@ -193,19 +175,16 @@ static int session_device_start(SessionDevice *sd) {
switch (sd->type) {
case DEVICE_TYPE_DRM:
-
if (sd->fd < 0) {
- /* Open device if it isn't open yet */
- sd->fd = session_device_open(sd, true);
- if (sd->fd < 0)
- return sd->fd;
- } else {
- /* 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;
+ log_error("Failed to re-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
+ return -EBADF;
}
+
+ /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
+ * keep the device paused. Maybe at some point we have a drmStealMaster(). */
+ r = sd_drmsetmaster(sd->fd);
+ if (r < 0)
+ return r;
break;
case DEVICE_TYPE_EVDEV:
@@ -239,6 +218,11 @@ static void session_device_stop(SessionDevice *sd) {
switch (sd->type) {
case DEVICE_TYPE_DRM:
+ if (sd->fd < 0) {
+ log_error("Failed to de-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
+ return;
+ }
+
/* On DRM devices we simply drop DRM-Master but keep it open.
* This allows the user to keep resources allocated. The
* CAP_SYS_ADMIN restriction to DRM-Master prevents users from
@@ -416,15 +400,21 @@ error:
void session_device_free(SessionDevice *sd) {
assert(sd);
+ /* Make sure to remove the pushed fd. */
if (sd->pushed_fd) {
- const char *m;
-
- /* Remove the pushed fd again, just in case. */
-
- m = strjoina("FDSTOREREMOVE=1\n"
- "FDNAME=session-", sd->session->id);
-
- (void) sd_notify(false, m);
+ _cleanup_free_ char *m = NULL;
+ const char *id;
+ int r;
+
+ /* Session ID does not contain separators. */
+ id = sd->session->id;
+ assert(*(id + strcspn(id, "-\n")) == '\0');
+
+ r = asprintf(&m, "FDSTOREREMOVE=1\n"
+ "FDNAME=session-%s-device-%u-%u\n",
+ id, major(sd->dev), minor(sd->dev));
+ if (r >= 0)
+ (void) sd_notify(false, m);
}
session_device_stop(sd);
@@ -510,7 +500,8 @@ unsigned int session_device_try_pause_all(Session *s) {
}
int session_device_save(SessionDevice *sd) {
- const char *m;
+ _cleanup_free_ char *m = NULL;
+ const char *id;
int r;
assert(sd);
@@ -525,8 +516,15 @@ int session_device_save(SessionDevice *sd) {
if (sd->pushed_fd)
return 0;
- m = strjoina("FDSTORE=1\n"
- "FDNAME=session-", sd->session->id);
+ /* Session ID does not contain separators. */
+ id = sd->session->id;
+ assert(*(id + strcspn(id, "-\n")) == '\0');
+
+ r = asprintf(&m, "FDSTORE=1\n"
+ "FDNAME=session-%s-device-%u-%u\n",
+ id, major(sd->dev), minor(sd->dev));
+ if (r < 0)
+ return r;
r = sd_pid_notify_with_fds(0, false, m, &sd->fd, 1);
if (r < 0)
diff --git a/src/login/logind-session-device.h b/src/login/logind-session-device.h
index a9ead7bdca..f42c0218c0 100644
--- a/src/login/logind-session-device.h
+++ b/src/login/logind-session-device.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 David Herrmann
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
typedef enum DeviceType DeviceType;
typedef struct SessionDevice SessionDevice;
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 1859150b5e..69d5a10319 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -180,7 +162,7 @@ int session_save(Session *s) {
if (!s->started)
return 0;
- r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, false);
+ r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -267,7 +249,6 @@ int session_save(Session *s) {
if (s->desktop) {
_cleanup_free_ char *escaped;
-
escaped = cescape(s->desktop);
if (!escaped) {
r = -ENOMEM;
@@ -379,7 +360,7 @@ int session_load(Session *s) {
assert(s);
- r = parse_env_file(s->state_file, NEWLINE,
+ r = parse_env_file(NULL, s->state_file, NEWLINE,
"REMOTE", &remote,
"SCOPE", &s->scope,
"SCOPE_JOB", &s->scope_job,
@@ -558,7 +539,7 @@ int session_activate(Session *s) {
return 0;
}
-static int session_start_scope(Session *s) {
+static int session_start_scope(Session *s, sd_bus_message *properties) {
int r;
assert(s);
@@ -583,7 +564,7 @@ static int session_start_scope(Session *s) {
description,
"systemd-logind.service",
"systemd-user-sessions.service",
- (uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */
+ properties,
&error,
&job);
if (r < 0) {
@@ -604,7 +585,7 @@ static int session_start_scope(Session *s) {
return 0;
}
-int session_start(Session *s) {
+int session_start(Session *s, sd_bus_message *properties) {
int r;
assert(s);
@@ -620,7 +601,7 @@ int session_start(Session *s) {
return r;
/* Create cgroup */
- r = session_start_scope(s);
+ r = session_start_scope(s, properties);
if (r < 0)
return r;
@@ -629,8 +610,7 @@ int session_start(Session *s) {
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
"LEADER="PID_FMT, s->leader,
- LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name),
- NULL);
+ LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name));
if (!dual_timestamp_is_set(&s->timestamp))
dual_timestamp_get(&s->timestamp);
@@ -685,9 +665,19 @@ static int session_stop_scope(Session *s, bool force) {
free(s->scope_job);
s->scope_job = job;
- } else
+ } else {
s->scope_job = mfree(s->scope_job);
+ /* With no killing, this session is allowed to persist in "closing" state indefinitely.
+ * Therefore session stop and session removal may be two distinct events.
+ * Session stop is quite significant on its own, let's log it. */
+ log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
+ "SESSION_ID=%s", s->id,
+ "USER_ID=%s", s->user->name,
+ "LEADER="PID_FMT, s->leader,
+ LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id));
+ }
+
return 0;
}
@@ -734,8 +724,7 @@ int session_finalize(Session *s) {
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
"LEADER="PID_FMT, s->leader,
- LOG_MESSAGE("Removed session %s.", s->id),
- NULL);
+ LOG_MESSAGE("Removed session %s.", s->id));
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
@@ -949,7 +938,7 @@ int session_create_fifo(Session *s) {
/* Create FIFO */
if (!s->fifo_path) {
- r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, false);
+ r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
return r;
@@ -1145,8 +1134,7 @@ void session_restore_vt(Session *s) {
* little dance to avoid having the terminal be available
* for reuse before we've cleaned it up.
*/
- old_fd = s->vtfd;
- s->vtfd = -1;
+ old_fd = TAKE_FD(s->vtfd);
vt = session_open_vt(s);
safe_close(old_fd);
@@ -1271,8 +1259,7 @@ int session_set_controller(Session *s, const char *sender, bool force, bool prep
}
session_release_controller(s, true);
- s->controller = name;
- name = NULL;
+ s->controller = TAKE_PTR(name);
session_save(s);
return 0;
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index 16a278c792..29ca399daf 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Session Session;
typedef enum KillWho KillWho;
@@ -140,7 +121,7 @@ void session_set_idle_hint(Session *s, bool b);
int session_get_locked_hint(Session *s);
void session_set_locked_hint(Session *s, bool b);
int session_create_fifo(Session *s);
-int session_start(Session *s);
+int session_start(Session *s, sd_bus_message *properties);
int session_stop(Session *s, bool force);
int session_finalize(Session *s);
int session_release(Session *s);
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index d5d086cfe0..c662a26b9f 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -30,6 +12,8 @@
#include "strv.h"
#include "user-util.h"
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", User, user_get_state, user_state_to_string);
+
static int property_get_display(
sd_bus *bus,
const char *path,
@@ -53,24 +37,6 @@ static int property_get_display(
return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p);
}
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- User *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", user_state_to_string(user_get_state(u)));
-}
-
static int property_get_sessions(
sd_bus *bus,
const char *path,
@@ -354,8 +320,7 @@ int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
}
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index f85564f221..8c4cd54a29 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -1,26 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
-#include <sys/mount.h>
#include <unistd.h>
#include <stdio_ext.h>
@@ -30,7 +11,6 @@
#include "bus-util.h"
#include "cgroup-util.h"
#include "clean-ipc.h"
-#include "conf-parser.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
@@ -40,11 +20,9 @@
#include "label.h"
#include "logind-user.h"
#include "mkdir.h"
-#include "mount-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "rm-rf.h"
-#include "smack-util.h"
#include "special.h"
#include "stdio-util.h"
#include "string-table.h"
@@ -100,8 +78,8 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (r < 0)
return r;
- *out = u;
- u = NULL;
+ *out = TAKE_PTR(u);
+
return 0;
}
@@ -143,7 +121,7 @@ static int user_save_internal(User *u) {
assert(u);
assert(u->state_file);
- r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, false);
+ r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -304,7 +282,7 @@ int user_load(User *u) {
assert(u);
- r = parse_env_file(u->state_file, NEWLINE,
+ r = parse_env_file(NULL, u->state_file, NEWLINE,
"SERVICE_JOB", &u->service_job,
"SLICE_JOB", &u->slice_job,
"DISPLAY", &display,
@@ -332,85 +310,6 @@ int user_load(User *u) {
return r;
}
-static int user_mkdir_runtime_path(User *u) {
- int r;
-
- assert(u);
-
- r = mkdir_safe_label("/run/user", 0755, 0, 0, false);
- if (r < 0)
- return log_error_errno(r, "Failed to create /run/user: %m");
-
- if (path_is_mount_point(u->runtime_path, NULL, 0) <= 0) {
- _cleanup_free_ char *t = NULL;
-
- r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s",
- u->uid, u->gid, u->manager->runtime_dir_size,
- mac_smack_use() ? ",smackfsroot=*" : "");
- if (r < 0)
- return log_oom();
-
- (void) mkdir_label(u->runtime_path, 0700);
-
- r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
- if (r < 0) {
- if (!IN_SET(errno, EPERM, EACCES)) {
- r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path);
- goto fail;
- }
-
- log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s, assuming containerized execution, ignoring: %m", u->runtime_path);
-
- r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid);
- if (r < 0) {
- log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
- goto fail;
- }
- }
-
- r = label_fix(u->runtime_path, false, false);
- if (r < 0)
- log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", u->runtime_path);
- }
-
- return 0;
-
-fail:
- /* Try to clean up, but ignore errors */
- (void) rmdir(u->runtime_path);
- return r;
-}
-
-static int user_start_slice(User *u) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *description;
- char *job;
- int r;
-
- assert(u);
-
- u->slice_job = mfree(u->slice_job);
- description = strjoina("User Slice of ", u->name);
-
- r = manager_start_slice(
- u->manager,
- u->slice,
- description,
- "systemd-logind.service",
- "systemd-user-sessions.service",
- u->manager->user_tasks_max,
- &error,
- &job);
- if (r >= 0)
- u->slice_job = job;
- else if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
- /* we don't fail due to this, let's try to continue */
- log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)",
- u->slice, bus_error_message(&error, r), error.name);
-
- return 0;
-}
-
static int user_start_service(User *u) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *job;
@@ -457,20 +356,9 @@ int user_start(User *u) {
*/
u->stopping = false;
- if (!u->started) {
+ if (!u->started)
log_debug("Starting services for new user %s.", u->name);
- /* Make XDG_RUNTIME_DIR */
- r = user_mkdir_runtime_path(u);
- if (r < 0)
- return r;
- }
-
- /* Create cgroup */
- r = user_start_slice(u);
- if (r < 0)
- return r;
-
/* Save the user data so far, because pam_systemd will read the
* XDG_RUNTIME_DIR out of it while starting up systemd --user.
* We need to do user_save_internal() because we have not
@@ -531,29 +419,6 @@ static int user_stop_service(User *u) {
return r;
}
-static int user_remove_runtime_path(User *u) {
- int r;
-
- assert(u);
-
- r = rm_rf(u->runtime_path, 0);
- if (r < 0)
- log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", u->runtime_path);
-
- /* Ignore cases where the directory isn't mounted, as that's
- * quite possible, if we lacked the permissions to mount
- * something */
- r = umount2(u->runtime_path, MNT_DETACH);
- if (r < 0 && !IN_SET(errno, EINVAL, ENOENT))
- log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
-
- r = rm_rf(u->runtime_path, REMOVE_ROOT);
- if (r < 0)
- log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", u->runtime_path);
-
- return r;
-}
-
int user_stop(User *u, bool force) {
Session *s;
int r = 0, k;
@@ -603,11 +468,6 @@ int user_finalize(User *u) {
r = k;
}
- /* Kill XDG_RUNTIME_DIR */
- k = user_remove_runtime_path(u);
- if (k < 0)
- r = k;
-
/* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs
* are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to
* system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such
@@ -842,7 +702,7 @@ int config_parse_tmpfs_size(
void *data,
void *userdata) {
- size_t *sz = data;
+ uint64_t *sz = data;
int r;
assert(filename);
@@ -871,8 +731,8 @@ int config_parse_tmpfs_size(
return 0;
}
-int config_parse_user_tasks_max(
- const char* unit,
+int config_parse_compat_user_tasks_max(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -883,45 +743,17 @@ int config_parse_user_tasks_max(
void *data,
void *userdata) {
- uint64_t *m = data;
- uint64_t k;
- int r;
-
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (isempty(rvalue)) {
- *m = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U);
- return 0;
- }
-
- if (streq(rvalue, "infinity")) {
- *m = CGROUP_LIMIT_MAX;
- return 0;
- }
-
- /* Try to parse as percentage */
- r = parse_percent(rvalue);
- if (r >= 0)
- k = system_tasks_max_scale(r, 100U);
- else {
-
- /* If the passed argument was not a percentage, or out of range, parse as byte size */
-
- r = safe_atou64(rvalue, &k);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse tasks maximum, ignoring: %s", rvalue);
- return 0;
- }
- }
-
- if (k <= 0 || k >= UINT64_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Tasks maximum out of range, ignoring: %s", rvalue);
- return 0;
- }
-
- *m = k;
+ log_syntax(unit, LOG_NOTICE, filename, line, 0,
+ "Support for option %s= has been removed.",
+ lvalue);
+ log_info("Hint: try creating /etc/systemd/system/user-.slice/50-limits.conf with:\n"
+ " [Slice]\n"
+ " TasksMax=%s",
+ rvalue);
return 0;
}
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index c3452dcd08..eba2325284 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -1,27 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct User User;
+#include "conf-parser.h"
#include "list.h"
#include "logind.h"
@@ -92,3 +74,5 @@ UserState user_state_from_string(const char *s) _pure_;
int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_compat_user_tasks_max);
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
index ab35d0e326..71ebdfcfb1 100644
--- a/src/login/logind-utmp.c
+++ b/src/login/logind-utmp.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <pwd.h>
diff --git a/src/login/logind.c b/src/login/logind.c
index 5220861c1d..52fcee933c 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -30,60 +12,31 @@
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-util.h"
-#include "conf-parser.h"
#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
#include "logind.h"
+#include "parse-util.h"
#include "process-util.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "strv.h"
#include "udev-util.h"
-static void manager_free(Manager *m);
-
-static void manager_reset_config(Manager *m) {
- m->n_autovts = 6;
- m->reserve_vt = 6;
- m->remove_ipc = true;
- m->inhibit_delay_max = 5 * USEC_PER_SEC;
- m->handle_power_key = HANDLE_POWEROFF;
- m->handle_suspend_key = HANDLE_SUSPEND;
- m->handle_hibernate_key = HANDLE_HIBERNATE;
- m->handle_lid_switch = HANDLE_SUSPEND;
- m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
- m->handle_lid_switch_docked = HANDLE_IGNORE;
- m->power_key_ignore_inhibited = false;
- m->suspend_key_ignore_inhibited = false;
- m->hibernate_key_ignore_inhibited = false;
- m->lid_switch_ignore_inhibited = true;
-
- m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
-
- m->idle_action_usec = 30 * USEC_PER_MINUTE;
- m->idle_action = HANDLE_IGNORE;
-
- m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
- m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
- m->sessions_max = 8192;
- m->inhibitors_max = 8192;
-
- m->kill_user_processes = KILL_USER_PROCESSES;
-
- m->kill_only_users = strv_free(m->kill_only_users);
- m->kill_exclude_users = strv_free(m->kill_exclude_users);
-}
+static Manager* manager_unref(Manager *m);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
-static Manager *manager_new(void) {
- Manager *m;
+static int manager_new(Manager **ret) {
+ _cleanup_(manager_unrefp) Manager *m = NULL;
int r;
+ assert(ret);
+
m = new0(Manager, 1);
if (!m)
- return NULL;
+ return -ENOMEM;
m->console_active_fd = -1;
m->reserve_vt_fd = -1;
@@ -101,28 +54,33 @@ static Manager *manager_new(void) {
m->session_units = hashmap_new(&string_hash_ops);
if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
- goto fail;
+ return -ENOMEM;
m->udev = udev_new();
if (!m->udev)
- goto fail;
+ return -errno;
r = sd_event_default(&m->event);
if (r < 0)
- goto fail;
+ return r;
- sd_event_set_watchdog(m->event, true);
+ r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
+ if (r < 0)
+ return r;
- manager_reset_config(m);
+ r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
+ if (r < 0)
+ return r;
- return m;
+ (void) sd_event_set_watchdog(m->event, true);
+
+ manager_reset_config(m);
-fail:
- manager_free(m);
- return NULL;
+ *ret = TAKE_PTR(m);
+ return 0;
}
-static void manager_free(Manager *m) {
+static Manager* manager_unref(Manager *m) {
Session *session;
User *u;
Device *d;
@@ -131,7 +89,7 @@ static void manager_free(Manager *m) {
Button *b;
if (!m)
- return;
+ return NULL;
while ((session = hashmap_first(m->sessions)))
session_free(session);
@@ -200,12 +158,13 @@ static void manager_free(Manager *m) {
free(m->scheduled_shutdown_tty);
free(m->wall_message);
free(m->action_job);
- free(m);
+
+ return mfree(m);
}
static int manager_enumerate_devices(Manager *m) {
struct udev_list_entry *item = NULL, *first = NULL;
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
int r;
assert(m);
@@ -231,7 +190,7 @@ static int manager_enumerate_devices(Manager *m) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
int k;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
@@ -247,7 +206,7 @@ static int manager_enumerate_devices(Manager *m) {
}
static int manager_enumerate_buttons(Manager *m) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
@@ -280,7 +239,7 @@ static int manager_enumerate_buttons(Manager *m) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
int k;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
@@ -411,6 +370,41 @@ static int manager_enumerate_users(Manager *m) {
return r;
}
+static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) {
+ _cleanup_strv_free_ char **parts = NULL;
+ _cleanup_free_ char *id = NULL;
+ unsigned int major, minor;
+ int r;
+
+ parts = strv_split(fdname, "-");
+ if (!parts)
+ return -ENOMEM;
+ if (strv_length(parts) != 5)
+ return -EINVAL;
+
+ if (!streq(parts[0], "session"))
+ return -EINVAL;
+
+ id = strdup(parts[1]);
+ if (!id)
+ return -ENOMEM;
+
+ if (!streq(parts[2], "device"))
+ return -EINVAL;
+
+ r = safe_atou(parts[3], &major);
+ if (r < 0)
+ return r;
+ r = safe_atou(parts[4], &minor);
+ if (r < 0)
+ return r;
+
+ *dev = makedev(major, minor);
+ *session_id = TAKE_PTR(id);
+
+ return 0;
+}
+
static int manager_attach_fds(Manager *m) {
_cleanup_strv_free_ char **fdnames = NULL;
int n, i, fd;
@@ -424,16 +418,21 @@ static int manager_attach_fds(Manager *m) {
return n;
for (i = 0; i < n; i++) {
+ _cleanup_free_ char *id = NULL;
+ dev_t dev;
struct stat st;
SessionDevice *sd;
Session *s;
- char *id;
+ int r;
fd = SD_LISTEN_FDS_START + i;
- id = startswith(fdnames[i], "session-");
- if (!id)
+ r = parse_fdname(fdnames[i], &id, &dev);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse fd name %s: %m", fdnames[i]);
+ close_nointr(fd);
continue;
+ }
s = hashmap_get(m->sessions, id);
if (!s) {
@@ -453,24 +452,24 @@ static int manager_attach_fds(Manager *m) {
continue;
}
- if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
- log_debug("Device fd doesn't actually point to device node: %m");
+ if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) {
+ log_debug("Device fd doesn't point to the expected character device node");
close_nointr(fd);
continue;
}
- sd = hashmap_get(s->devices, &st.st_rdev);
+ sd = hashmap_get(s->devices, &dev);
if (!sd) {
/* Weird, we got an fd for a session device which wasn't
- * recorded in the session state file... */
+ * recorded in the session state file... */
log_warning("Got fd for missing session device [%u:%u] in session %s",
- major(st.st_rdev), minor(st.st_rdev), s->id);
+ major(dev), minor(dev), s->id);
close_nointr(fd);
continue;
}
log_debug("Attaching fd to session device [%u:%u] for session %s",
- major(st.st_rdev), minor(st.st_rdev), s->id);
+ major(dev), minor(dev), s->id);
session_device_attach_fd(sd, fd, s->was_active);
}
@@ -567,7 +566,7 @@ static int manager_enumerate_inhibitors(Manager *m) {
}
static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
Manager *m = userdata;
assert(m);
@@ -581,7 +580,7 @@ static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t reven
}
static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
Manager *m = userdata;
assert(m);
@@ -595,7 +594,7 @@ static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t rev
}
static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
Manager *m = userdata;
const char *name;
@@ -617,7 +616,7 @@ static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t reven
}
static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
Manager *m = userdata;
assert(m);
@@ -1067,16 +1066,6 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
return 0;
}
-static int manager_parse_config_file(Manager *m) {
- assert(m);
-
- return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
- CONF_PATHS_NULSTR("systemd/logind.conf.d"),
- "Login\0",
- config_item_perf_lookup, logind_gperf_lookup,
- CONFIG_PARSE_WARN, m);
-}
-
static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
Manager *m = userdata;
int r;
@@ -1102,8 +1091,6 @@ static int manager_startup(Manager *m) {
assert(m);
- assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0);
-
r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
if (r < 0)
return log_error_errno(r, "Failed to register SIGHUP handler: %m");
@@ -1171,7 +1158,7 @@ static int manager_startup(Manager *m) {
user_start(user);
HASHMAP_FOREACH(session, m->sessions, i)
- session_start(session);
+ session_start(session, NULL);
HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
inhibitor_start(inhibitor);
@@ -1211,7 +1198,7 @@ static int manager_run(Manager *m) {
}
int main(int argc, char *argv[]) {
- Manager *m = NULL;
+ _cleanup_(manager_unrefp) Manager *m = NULL;
int r;
log_set_target(LOG_TARGET_AUTO);
@@ -1233,22 +1220,22 @@ int main(int argc, char *argv[]) {
goto finish;
}
- /* Always create the directories people can create inotify
- * watches in. Note that some applications might check for the
- * existence of /run/systemd/seats/ to determine whether
- * logind is available, so please always make sure this check
- * stays in. */
- mkdir_label("/run/systemd/seats", 0755);
- mkdir_label("/run/systemd/users", 0755);
- mkdir_label("/run/systemd/sessions", 0755);
-
- m = manager_new();
- if (!m) {
- r = log_oom();
+ /* Always create the directories people can create inotify watches in. Note that some applications might check
+ * for the existence of /run/systemd/seats/ to determine whether logind is available, so please always make
+ * sure these directories are created early on and unconditionally. */
+ (void) mkdir_label("/run/systemd/seats", 0755);
+ (void) mkdir_label("/run/systemd/users", 0755);
+ (void) mkdir_label("/run/systemd/sessions", 0755);
+
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, -1) >= 0);
+
+ r = manager_new(&m);
+ if (r < 0) {
+ log_error_errno(r, "Failed to allocate manager object: %m");
goto finish;
}
- manager_parse_config_file(m);
+ (void) manager_parse_config_file(m);
r = manager_startup(m);
if (r < 0) {
@@ -1258,20 +1245,18 @@ int main(int argc, char *argv[]) {
log_debug("systemd-logind running as pid "PID_FMT, getpid_cached());
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
+ (void) sd_notify(false,
+ "READY=1\n"
+ "STATUS=Processing requests...");
r = manager_run(m);
log_debug("systemd-logind stopped as pid "PID_FMT, getpid_cached());
-finish:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- manager_free(m);
+ (void) sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down...");
+finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in
index 40a77dc7be..1029e29bc7 100644
--- a/src/login/logind.conf.in
+++ b/src/login/logind.conf.in
@@ -35,4 +35,3 @@
#RemoveIPC=yes
#InhibitorsMax=8192
#SessionsMax=8192
-#UserTasksMax=33%
diff --git a/src/login/logind.h b/src/login/logind.h
index 918bc1f919..a6ebc9e152 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -1,31 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "libudev.h"
#include "sd-bus.h"
#include "sd-event.h"
+#include "conf-parser.h"
#include "hashmap.h"
#include "list.h"
#include "set.h"
@@ -133,12 +115,15 @@ struct Manager {
usec_t holdoff_timeout_usec;
sd_event_source *lid_switch_ignore_event_source;
- size_t runtime_dir_size;
+ uint64_t runtime_dir_size;
uint64_t user_tasks_max;
uint64_t sessions_max;
uint64_t inhibitors_max;
};
+void manager_reset_config(Manager *m);
+int manager_parse_config_file(Manager *m);
+
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device);
int manager_add_button(Manager *m, const char *name, Button **_button);
int manager_add_seat(Manager *m, const char *id, Seat **_seat);
@@ -176,8 +161,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
-int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_message *more_properties, sd_bus_error *error, char **job);
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
@@ -190,9 +174,8 @@ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE
int manager_set_lid_switch_ignore(Manager *m, usec_t until);
-int config_parse_n_autovts(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tmpfs_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_user_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_n_autovts);
+CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs_size);
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
diff --git a/src/login/meson.build b/src/login/meson.build
index 5b75382e5f..4326a452c6 100644
--- a/src/login/meson.build
+++ b/src/login/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
systemd_logind_sources = files('''
logind.c
@@ -26,9 +11,6 @@ logind_gperf_c = custom_target(
output : 'logind-gperf.c',
command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
-systemd_logind_sources += [logind_gperf_c]
-
-
liblogind_core_sources = files('''
logind-core.c
logind-device.c
@@ -55,6 +37,8 @@ liblogind_core_sources = files('''
logind-acl.h
'''.split())
+liblogind_core_sources += [logind_gperf_c]
+
logind_acl_c = files('logind-acl.c')
if conf.get('HAVE_ACL') == 1
liblogind_core_sources += logind_acl_c
@@ -72,6 +56,11 @@ loginctl_sources = files('''
sysfs-show.c
'''.split())
+user_runtime_dir_sources = files('''
+ user-runtime-dir.c
+ logind.h
+'''.split())
+
if conf.get('ENABLE_LOGIND') == 1
logind_conf = configure_file(
input : 'logind.conf.in',
@@ -107,7 +96,7 @@ if conf.get('ENABLE_LOGIND') == 1
'73-seat-late.rules',
input : '73-seat-late.rules.m4',
output: '73-seat-late.rules',
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : true,
install_dir : udevrulesdir)
@@ -116,7 +105,7 @@ if conf.get('ENABLE_LOGIND') == 1
'systemd-user',
input : 'systemd-user.m4',
output: 'systemd-user',
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : pamconfdir != 'no',
install_dir : pamconfdir)
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index d842411781..f880f3e2da 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -152,6 +152,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="SuspendThenHibernate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="CanPowerOff"/>
<allow send_destination="org.freedesktop.login1"
@@ -176,6 +180,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="CanSuspendThenHibernate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="ScheduleShutdown"/>
<allow send_destination="org.freedesktop.login1"
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index 1c3ba33e23..1fbf6ba585 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <endian.h>
#include <errno.h>
@@ -48,6 +30,7 @@
#include "terminal-util.h"
#include "util.h"
#include "path-util.h"
+#include "cgroup-util.h"
static int parse_argv(
pam_handle_t *handle,
@@ -211,13 +194,93 @@ error:
return r;
}
+static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
+ uint64_t val;
+ int r;
+
+ if (isempty(limit))
+ return 0;
+
+ if (streq(limit, "infinity")) {
+ r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", (uint64_t)-1);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else {
+ r = parse_percent(limit);
+ if (r >= 0) {
+ r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U));
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else {
+ r = parse_size(limit, 1024, &val);
+ if (r >= 0) {
+ r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", val);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else
+ pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.limit: %s, ignoring.", limit);
+ }
+ }
+
+ return 0;
+}
+
+static int append_session_tasks_max(pam_handle_t *handle, sd_bus_message *m, const char *limit)
+{
+ uint64_t val;
+ int r;
+
+ /* No need to parse "infinity" here, it will be set unconditionally later in manager_start_scope() */
+ if (isempty(limit) || streq(limit, "infinity"))
+ return 0;
+
+ r = safe_atou64(limit, &val);
+ if (r >= 0) {
+ r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", val);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else
+ pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.limit: %s, ignoring.", limit);
+
+ return 0;
+}
+
+static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit, const char *field) {
+ uint64_t val;
+ int r;
+
+ if (!isempty(limit)) {
+ r = cg_weight_parse(limit, &val);
+ if (r >= 0) {
+ r = sd_bus_message_append(m, "(sv)", field, "t", val);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else if (streq(field, "CPUWeight"))
+ pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight: %s, ignoring.", limit);
+ else
+ pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.io_weight: %s, ignoring.", limit);
+ }
+
+ return 0;
+}
+
_public_ PAM_EXTERN int pam_sm_open_session(
pam_handle_t *handle,
int flags,
int argc, const char **argv) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
const char
*username, *id, *object_path, *runtime_path,
*service = NULL,
@@ -225,7 +288,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
*remote_user = NULL, *remote_host = NULL,
*seat = NULL,
*type = NULL, *class = NULL,
- *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL;
+ *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL,
+ *memory_max = NULL, *tasks_max = NULL, *cpu_weight = NULL, *io_weight = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int session_fd = -1, existing, r;
bool debug = false, remote;
@@ -366,6 +430,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
remote = !isempty(remote_host) && !is_localhost(remote_host);
+ (void) pam_get_data(handle, "systemd.memory_max", (const void **)&memory_max);
+ (void) pam_get_data(handle, "systemd.tasks_max", (const void **)&tasks_max);
+ (void) pam_get_data(handle, "systemd.cpu_weight", (const void **)&cpu_weight);
+ (void) pam_get_data(handle, "systemd.io_weight", (const void **)&io_weight);
+
/* Talk to logind over the message bus */
r = sd_bus_open_system(&bus);
@@ -374,7 +443,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
return PAM_SESSION_ERR;
}
- if (debug)
+ if (debug) {
pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: "
"uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
pw->pw_uid, getpid_cached(),
@@ -382,29 +451,71 @@ _public_ PAM_EXTERN int pam_sm_open_session(
type, class, strempty(desktop),
strempty(seat), vtnr, strempty(tty), strempty(display),
yes_no(remote), strempty(remote_user), strempty(remote_host));
+ pam_syslog(handle, LOG_DEBUG, "Session limits: "
+ "memory_max=%s tasks_max=%s cpu_weight=%s io_weight=%s",
+ strna(memory_max), strna(tasks_max), strna(cpu_weight), strna(io_weight));
+ }
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "CreateSession");
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to create CreateSession method call: %s", strerror(-r));
+ return PAM_SESSION_ERR;
+ }
+
+ r = sd_bus_message_append(m, "uusssssussbss",
+ (uint32_t) pw->pw_uid,
+ (uint32_t) getpid_cached(),
+ service,
+ type,
+ class,
+ desktop,
+ seat,
+ vtnr,
+ tty,
+ display,
+ remote,
+ remote_user,
+ remote_host);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return PAM_SESSION_ERR;
+ }
+
+ r = sd_bus_message_open_container(m, 'a', "(sv)");
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to open message container: %s", strerror(-r));
+ return PAM_SYSTEM_ERR;
+ }
+
+ r = append_session_memory_max(handle, m, memory_max);
+ if (r < 0)
+ return PAM_SESSION_ERR;
+
+ r = append_session_tasks_max(handle, m, tasks_max);
+ if (r < 0)
+ return PAM_SESSION_ERR;
+
+ r = append_session_cg_weight(handle, m, cpu_weight, "CPUWeight");
+ if (r < 0)
+ return PAM_SESSION_ERR;
+
+ r = append_session_cg_weight(handle, m, io_weight, "IOWeight");
+ if (r < 0)
+ return PAM_SESSION_ERR;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to close message container: %s", strerror(-r));
+ return PAM_SYSTEM_ERR;
+ }
- r = sd_bus_call_method(bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "CreateSession",
- &error,
- &reply,
- "uusssssussbssa(sv)",
- (uint32_t) pw->pw_uid,
- (uint32_t) getpid_cached(),
- service,
- type,
- class,
- desktop,
- seat,
- vtnr,
- tty,
- display,
- remote,
- remote_user,
- remote_host,
- 0);
+ r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) {
pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r));
diff --git a/src/login/pam_systemd.sym b/src/login/pam_systemd.sym
index d48b9e8ccd..62d5d26b04 100644
--- a/src/login/pam_systemd.sym
+++ b/src/login/pam_systemd.sym
@@ -1,8 +1,6 @@
/***
SPDX-License-Identifier: LGPL-2.1+
- 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
diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c
index ca8bfa2677..d5c347be0c 100644
--- a/src/login/sysfs-show.c
+++ b/src/login/sysfs-show.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -56,7 +38,7 @@ static int show_sysfs_one(
max_width = n_columns;
while (*item) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
struct udev_list_entry *next, *lookahead;
const char *sn, *name, *sysfs, *subsystem, *sysname;
_cleanup_free_ char *k = NULL, *l = NULL;
@@ -99,7 +81,7 @@ static int show_sysfs_one(
if (path_startswith(lookahead_sysfs, sub) &&
!path_startswith(lookahead_sysfs, sysfs)) {
- _cleanup_udev_device_unref_ struct udev_device *lookahead_d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *lookahead_d = NULL;
lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs);
if (lookahead_d) {
@@ -155,8 +137,8 @@ static int show_sysfs_one(
}
int show_sysfs(const char *seat, const char *prefix, unsigned n_columns, OutputFlags flags) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
struct udev_list_entry *first = NULL;
int r;
diff --git a/src/login/sysfs-show.h b/src/login/sysfs-show.h
index 15c902cc3a..c05b977532 100644
--- a/src/login/sysfs-show.h
+++ b/src/login/sysfs-show.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/types.h>
#include "output-mode.h"
diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c
index ad4700f328..75c9303ff3 100644
--- a/src/login/test-inhibit.c
+++ b/src/login/test-inhibit.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
diff --git a/src/login/test-login-shared.c b/src/login/test-login-shared.c
index bf08b6ee9f..02ff57ab10 100644
--- a/src/login/test-login-shared.c
+++ b/src/login/test-login-shared.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "login-util.h"
#include "macro.h"
diff --git a/src/login/test-login-tables.c b/src/login/test-login-tables.c
index 7772f4b854..02b871968e 100644
--- a/src/login/test-login-tables.c
+++ b/src/login/test-login-tables.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "logind-action.h"
#include "logind-session.h"
diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c
new file mode 100644
index 0000000000..1bb26c99e4
--- /dev/null
+++ b/src/login/user-runtime-dir.c
@@ -0,0 +1,170 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdint.h>
+#include <sys/mount.h>
+
+#include "fs-util.h"
+#include "label.h"
+#include "logind.h"
+#include "mkdir.h"
+#include "mount-util.h"
+#include "path-util.h"
+#include "rm-rf.h"
+#include "smack-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "user-util.h"
+
+static int gather_configuration(size_t *runtime_dir_size) {
+ Manager m = {};
+ int r;
+
+ manager_reset_config(&m);
+
+ r = manager_parse_config_file(&m);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse logind.conf: %m");
+
+ *runtime_dir_size = m.runtime_dir_size;
+ return 0;
+}
+
+static int user_mkdir_runtime_path(const char *runtime_path, uid_t uid, gid_t gid, size_t runtime_dir_size) {
+ int r;
+
+ assert(runtime_path);
+ assert(path_is_absolute(runtime_path));
+ assert(uid_is_valid(uid));
+ assert(gid_is_valid(gid));
+
+ r = mkdir_safe_label("/run/user", 0755, 0, 0, MKDIR_WARN_MODE);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create /run/user: %m");
+
+ if (path_is_mount_point(runtime_path, NULL, 0) >= 0)
+ log_debug("%s is already a mount point", runtime_path);
+ else {
+ char options[sizeof("mode=0700,uid=,gid=,size=,smackfsroot=*")
+ + DECIMAL_STR_MAX(uid_t)
+ + DECIMAL_STR_MAX(gid_t)
+ + DECIMAL_STR_MAX(size_t)];
+
+ xsprintf(options,
+ "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s",
+ uid, gid, runtime_dir_size,
+ mac_smack_use() ? ",smackfsroot=*" : "");
+
+ (void) mkdir_label(runtime_path, 0700);
+
+ r = mount("tmpfs", runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, options);
+ if (r < 0) {
+ if (!IN_SET(errno, EPERM, EACCES)) {
+ r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", runtime_path);
+ goto fail;
+ }
+
+ log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s.\n"
+ "Assuming containerized execution, ignoring: %m", runtime_path);
+
+ r = chmod_and_chown(runtime_path, 0700, uid, gid);
+ if (r < 0) {
+ log_error_errno(r, "Failed to change ownership and mode of \"%s\": %m", runtime_path);
+ goto fail;
+ }
+ }
+
+ r = label_fix(runtime_path, 0);
+ if (r < 0)
+ log_warning_errno(r, "Failed to fix label of \"%s\", ignoring: %m", runtime_path);
+ }
+
+ return 0;
+
+fail:
+ /* Try to clean up, but ignore errors */
+ (void) rmdir(runtime_path);
+ return r;
+}
+
+static int user_remove_runtime_path(const char *runtime_path) {
+ int r;
+
+ assert(runtime_path);
+ assert(path_is_absolute(runtime_path));
+
+ r = rm_rf(runtime_path, 0);
+ if (r < 0)
+ log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", runtime_path);
+
+ /* Ignore cases where the directory isn't mounted, as that's
+ * quite possible, if we lacked the permissions to mount
+ * something */
+ r = umount2(runtime_path, MNT_DETACH);
+ if (r < 0 && !IN_SET(errno, EINVAL, ENOENT))
+ log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", runtime_path);
+
+ r = rm_rf(runtime_path, REMOVE_ROOT);
+ if (r < 0)
+ log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", runtime_path);
+
+ return r;
+}
+
+static int do_mount(const char *runtime_path, uid_t uid, gid_t gid) {
+ size_t runtime_dir_size;
+
+ assert_se(gather_configuration(&runtime_dir_size) == 0);
+
+ log_debug("Will mount %s owned by "UID_FMT":"GID_FMT, runtime_path, uid, gid);
+ return user_mkdir_runtime_path(runtime_path, uid, gid, runtime_dir_size);
+}
+
+static int do_umount(const char *runtime_path) {
+ log_debug("Will remove %s", runtime_path);
+ return user_remove_runtime_path(runtime_path);
+}
+
+int main(int argc, char *argv[]) {
+ const char *user;
+ uid_t uid;
+ gid_t gid;
+ char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)];
+ int r;
+
+ log_parse_environment();
+ log_open();
+
+ if (argc != 3) {
+ log_error("This program takes two arguments.");
+ return EXIT_FAILURE;
+ }
+ if (!STR_IN_SET(argv[1], "start", "stop")) {
+ log_error("First argument must be either \"start\" or \"stop\".");
+ return EXIT_FAILURE;
+ }
+
+ umask(0022);
+
+ user = argv[2];
+ r = get_user_creds(&user, &uid, &gid, NULL, NULL);
+ if (r < 0) {
+ log_error_errno(r,
+ r == -ESRCH ? "No such user \"%s\"" :
+ r == -ENOMSG ? "UID \"%s\" is invalid or has an invalid main group"
+ : "Failed to look up user \"%s\": %m",
+ user);
+ return EXIT_FAILURE;
+ }
+
+ xsprintf(runtime_path, "/run/user/" UID_FMT, uid);
+
+ if (streq(argv[1], "start"))
+ r = do_mount(runtime_path, uid, gid);
+ else if (streq(argv[1], "stop"))
+ r = do_umount(runtime_path);
+ else
+ assert_not_reached("Unknown verb!");
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c
index de6d869d30..966fd8e404 100644
--- a/src/machine-id-setup/machine-id-setup-main.c
+++ b/src/machine-id-setup/machine-id-setup-main.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index 8ba1380c81..89df274544 100644
--- a/src/machine/image-dbus.c
+++ b/src/machine/image-dbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/file.h>
#include <sys/mount.h>
@@ -448,8 +430,10 @@ int image_object_find(sd_bus *bus, const char *path, const char *interface, void
if (r < 0)
return r;
- r = image_find(e, &image);
- if (r <= 0)
+ r = image_find(IMAGE_MACHINE, e, &image);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
return r;
image->userdata = m;
@@ -491,7 +475,7 @@ int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char **
if (!images)
return -ENOMEM;
- r = image_discover(images);
+ r = image_discover(IMAGE_MACHINE, images);
if (r < 0)
return r;
@@ -507,8 +491,7 @@ int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char **
return r;
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/machine/image-dbus.h b/src/machine/image-dbus.h
index 119c69c25a..a918b77d38 100644
--- a/src/machine/image-dbus.h
+++ b/src/machine/image-dbus.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "machined.h"
extern const sd_bus_vtable image_vtable[];
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 9c435d6715..7f41465ccd 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -45,6 +27,7 @@
#include "machine-dbus.h"
#include "machine.h"
#include "mkdir.h"
+#include "os-util.h"
#include "path-util.h"
#include "process-util.h"
#include "signal-util.h"
@@ -52,31 +35,8 @@
#include "terminal-util.h"
#include "user-util.h"
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Machine *m = userdata;
- const char *state;
- int r;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- state = machine_state_to_string(machine_get_state(m));
-
- r = sd_bus_message_append_basic(reply, 's', state);
- if (r < 0)
- return r;
-
- return 1;
-}
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Machine, machine_get_state, machine_state_to_string);
static int property_get_netif(
sd_bus *bus,
@@ -98,8 +58,6 @@ static int property_get_netif(
return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
}
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
-
int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Machine *m = userdata;
int r;
@@ -368,7 +326,7 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
switch (m->class) {
case MACHINE_HOST:
- r = load_env_file_pairs(NULL, "/etc/os-release", NULL, &l);
+ r = load_os_release_pairs(NULL, &l);
if (r < 0)
return r;
@@ -399,13 +357,10 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
if (r < 0)
_exit(EXIT_FAILURE);
- fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0 && errno == ENOENT) {
- fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0 && errno == ENOENT)
- _exit(EXIT_NOT_FOUND);
- }
- if (fd < 0)
+ r = open_os_release(NULL, NULL, &fd);
+ if (r == -ENOENT)
+ _exit(EXIT_NOT_FOUND);
+ if (r < 0)
_exit(EXIT_FAILURE);
r = copy_bytes(fd, pair[1], (uint64_t) -1, 0);
@@ -522,8 +477,7 @@ static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {
if (r < 0)
return r;
- *ret = bus;
- bus = NULL;
+ *ret = TAKE_PTR(bus);
break;
}
@@ -647,8 +601,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
} else {
if (!path_is_absolute(path))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path '%s' is not absolute", path);
- args = args_wire;
- args_wire = NULL;
+ args = TAKE_PTR(args_wire);
if (strv_isempty(args)) {
args = strv_free(args);
@@ -907,7 +860,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
if (laccess(p, F_OK) < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
- r = chase_symlinks(src, NULL, 0, &chased_src);
+ r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to resolve source path: %m");
@@ -1475,8 +1428,7 @@ int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
return r;
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
@@ -1507,8 +1459,7 @@ int machine_send_create_reply(Machine *m, sd_bus_error *error) {
if (!m->create_message)
return 0;
- c = m->create_message;
- m->create_message = NULL;
+ c = TAKE_PTR(m->create_message);
if (error)
return sd_bus_reply_method_error(c, error);
diff --git a/src/machine/machine-dbus.h b/src/machine/machine-dbus.h
index f8c931fc38..f880803dc2 100644
--- a/src/machine/machine-dbus.h
+++ b/src/machine/machine-dbus.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
#include "machine.h"
@@ -44,5 +25,3 @@ int bus_machine_method_get_uid_shift(sd_bus_message *message, void *userdata, sd
int machine_send_signal(Machine *m, bool new_machine);
int machine_send_create_reply(Machine *m, sd_bus_error *error);
-
-int bus_reply_pair_array(sd_bus_message *m, char **l);
diff --git a/src/machine/machine.c b/src/machine/machine.c
index 4bacf91d26..b645f614c4 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -131,7 +113,7 @@ int machine_save(Machine *m) {
if (!m->started)
return 0;
- r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, false);
+ r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -249,7 +231,6 @@ static void machine_unlink(Machine *m) {
assert(m);
if (m->unit) {
-
char *sl;
sl = strjoina("/run/systemd/machines/unit:", m->unit);
@@ -269,7 +250,7 @@ int machine_load(Machine *m) {
if (!m->state_file)
return 0;
- r = parse_env_file(m->state_file, NEWLINE,
+ r = parse_env_file(NULL, m->state_file, NEWLINE,
"SCOPE", &m->unit,
"SCOPE_JOB", &m->scope_job,
"SERVICE", &m->service,
@@ -409,8 +390,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
"MESSAGE_ID=" SD_MESSAGE_MACHINE_START_STR,
"NAME=%s", m->name,
"LEADER="PID_FMT, m->leader,
- LOG_MESSAGE("New machine %s.", m->name),
- NULL);
+ LOG_MESSAGE("New machine %s.", m->name));
if (!dual_timestamp_is_set(&m->timestamp))
dual_timestamp_get(&m->timestamp);
@@ -472,8 +452,7 @@ int machine_finalize(Machine *m) {
"MESSAGE_ID=" SD_MESSAGE_MACHINE_STOP_STR,
"NAME=%s", m->name,
"LEADER="PID_FMT, m->leader,
- LOG_MESSAGE("Machine %s terminated.", m->name),
- NULL);
+ LOG_MESSAGE("Machine %s terminated.", m->name));
machine_unlink(m);
machine_add_to_gc_queue(m);
diff --git a/src/machine/machine.h b/src/machine/machine.h
index 1ef5dcdb89..946838f86f 100644
--- a/src/machine/machine.h
+++ b/src/machine/machine.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct Machine Machine;
typedef enum KillWho KillWho;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index e695bdbab4..d656681daf 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <errno.h>
@@ -42,8 +24,10 @@
#include "copy.h"
#include "env-util.h"
#include "fd-util.h"
+#include "format-table.h"
#include "hostname-util.h"
#include "import-util.h"
+#include "locale-util.h"
#include "log.h"
#include "logs-show.h"
#include "macro.h"
@@ -57,6 +41,7 @@
#include "signal-util.h"
#include "spawn-polkit-agent.h"
#include "stdio-util.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit-name.h"
@@ -89,8 +74,6 @@ static const char *arg_uid = NULL;
static char **arg_setenv = NULL;
static int arg_addrs = 1;
-static int print_addresses(sd_bus *bus, const char *name, int, const char *pr1, const char *pr2, int n_addr);
-
static OutputFlags get_output_flags(void) {
return
arg_all * OUTPUT_SHOW_ALL |
@@ -99,34 +82,8 @@ static OutputFlags get_output_flags(void) {
!arg_quiet * OUTPUT_WARN_CUTOFF;
}
-typedef struct MachineInfo {
- const char *name;
- const char *class;
- const char *service;
- char *os;
- char *version_id;
-} MachineInfo;
-
-static int compare_machine_info(const void *a, const void *b) {
- const MachineInfo *x = a, *y = b;
-
- return strcmp(x->name, y->name);
-}
-
-static void clean_machine_info(MachineInfo *machines, size_t n_machines) {
- size_t i;
-
- if (!machines || n_machines == 0)
- return;
-
- for (i = 0; i < n_machines; i++) {
- free(machines[i].os);
- free(machines[i].version_id);
- }
- free(machines);
-}
-
static int call_get_os_release(sd_bus *bus, const char *method, const char *name, const char *query, ...) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *k, *v, *iter, **query_res = NULL;
size_t count = 0, awaited_args = 0;
@@ -147,9 +104,10 @@ static int call_get_os_release(sd_bus *bus, const char *method, const char *name
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
method,
- NULL, &reply, "s", name);
+ &error,
+ &reply, "s", name);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to call '%s()': %s", method, bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "{ss}");
if (r < 0)
@@ -192,279 +150,281 @@ static int call_get_os_release(sd_bus *bus, const char *method, const char *name
return 0;
}
-static int list_machines(int argc, char *argv[], void *userdata) {
+static int call_get_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2, int n_addr, char **ret) {
- size_t max_name = STRLEN("MACHINE"), max_class = STRLEN("CLASS"),
- max_service = STRLEN("SERVICE"), max_os = STRLEN("OS"), max_version_id = STRLEN("VERSION");
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ char *prefix = NULL;
- MachineInfo *machines = NULL;
- const char *name, *class, *service, *object;
- size_t n_machines = 0, n_allocated = 0, j;
- sd_bus *bus = userdata;
+ _cleanup_free_ char *addresses = NULL;
+ bool truncate = false;
+ unsigned n = 0;
int r;
assert(bus);
-
- pager_open(arg_no_pager, false);
+ assert(name);
+ assert(prefix);
+ assert(prefix2);
r = sd_bus_call_method(bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
- "ListMachines",
- &error,
+ "GetMachineAddresses",
+ NULL,
&reply,
- NULL);
- if (r < 0) {
- log_error("Could not get machines: %s", bus_error_message(&error, -r));
- return r;
- }
+ "s", name);
+ if (r < 0)
+ return log_debug_errno(r, "Could not get addresses: %s", bus_error_message(&error, r));
- r = sd_bus_message_enter_container(reply, 'a', "(ssso)");
+ addresses = strdup(prefix);
+ if (!addresses)
+ return log_oom();
+ prefix = "";
+
+ r = sd_bus_message_enter_container(reply, 'a', "(iay)");
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
- size_t l;
- if (name[0] == '.' && !arg_all)
- continue;
-
- if (!GREEDY_REALLOC0(machines, n_allocated, n_machines + 1)) {
- r = log_oom();
- goto out;
- }
+ while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
+ int family;
+ const void *a;
+ size_t sz;
+ char buf_ifi[DECIMAL_STR_MAX(int) + 2], buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
- machines[n_machines].name = name;
- machines[n_machines].class = class;
- machines[n_machines].service = service;
+ r = sd_bus_message_read(reply, "i", &family);
+ if (r < 0)
+ return bus_log_parse_error(r);
- (void) call_get_os_release(
- bus,
- "GetMachineOSRelease",
- name,
- "ID\0"
- "VERSION_ID\0",
- &machines[n_machines].os,
- &machines[n_machines].version_id);
+ r = sd_bus_message_read_array(reply, 'y', &a, &sz);
+ if (r < 0)
+ return bus_log_parse_error(r);
- l = strlen(name);
- if (l > max_name)
- max_name = l;
+ if (n_addr != 0) {
+ if (family == AF_INET6 && ifi > 0)
+ xsprintf(buf_ifi, "%%%i", ifi);
+ else
+ strcpy(buf_ifi, "");
- l = strlen(class);
- if (l > max_class)
- max_class = l;
+ if (!strextend(&addresses, prefix, inet_ntop(family, a, buffer, sizeof(buffer)), buf_ifi, NULL))
+ return log_oom();
+ } else
+ truncate = true;
- l = strlen(service);
- if (l > max_service)
- max_service = l;
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
- l = machines[n_machines].os ? strlen(machines[n_machines].os) : 1;
- if (l > max_os)
- max_os = l;
+ prefix = prefix2;
- l = machines[n_machines].version_id ? strlen(machines[n_machines].version_id) : 1;
- if (l > max_version_id)
- max_version_id = l;
+ if (n_addr > 0)
+ n_addr --;
- n_machines++;
- }
- if (r < 0) {
- r = bus_log_parse_error(r);
- goto out;
+ n++;
}
+ if (r < 0)
+ return bus_log_parse_error(r);
r = sd_bus_message_exit_container(reply);
- if (r < 0) {
- r = bus_log_parse_error(r);
- goto out;
- }
+ if (r < 0)
+ return bus_log_parse_error(r);
- qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info);
+ if (truncate) {
- /* Allocate for prefix max characters for all fields + spaces between them + STRLEN(",\n") */
- r = asprintf(&prefix, "%-*s",
- (int) (max_name +
- max_class +
- max_service +
- max_os +
- max_version_id + 5 + STRLEN(",\n")),
- ",\n");
- if (r < 0) {
- r = log_oom();
- goto out;
- }
-
- if (arg_legend && n_machines > 0)
- printf("%-*s %-*s %-*s %-*s %-*s %s\n",
- (int) max_name, "MACHINE",
- (int) max_class, "CLASS",
- (int) max_service, "SERVICE",
- (int) max_os, "OS",
- (int) max_version_id, "VERSION",
- "ADDRESSES");
-
- for (j = 0; j < n_machines; j++) {
- printf("%-*s %-*s %-*s %-*s %-*s ",
- (int) max_name, machines[j].name,
- (int) max_class, machines[j].class,
- (int) max_service, strdash_if_empty(machines[j].service),
- (int) max_os, strdash_if_empty(machines[j].os),
- (int) max_version_id, strdash_if_empty(machines[j].version_id));
-
- r = print_addresses(bus, machines[j].name, 0, "", prefix, arg_addrs);
- if (r <= 0) /* error or no addresses defined? */
- fputs("-\n", stdout);
- else
- fputc('\n', stdout);
- }
+ if (!strextend(&addresses, special_glyph(ELLIPSIS), NULL))
+ return -ENOMEM;
- if (arg_legend) {
- if (n_machines > 0)
- printf("\n%zu machines listed.\n", n_machines);
- else
- printf("No machines.\n");
}
- r = 0;
-out:
- clean_machine_info(machines, n_machines);
- return r;
+ *ret = TAKE_PTR(addresses);
+ return (int) n;
}
-typedef struct ImageInfo {
- const char *name;
- const char *type;
- bool read_only;
- usec_t crtime;
- usec_t mtime;
- uint64_t size;
-} ImageInfo;
+static int show_table(Table *table, const char *word) {
+ int r;
-static int compare_image_info(const void *a, const void *b) {
- const ImageInfo *x = a, *y = b;
+ assert(table);
+ assert(word);
- return strcmp(x->name, y->name);
+ if (table_get_rows(table) > 1) {
+ r = table_set_sort(table, (size_t) 0, (size_t) -1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to sort table: %m");
+
+ table_set_header(table, arg_legend);
+
+ r = table_print(table, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to show table: %m");
+ }
+
+ if (arg_legend) {
+ if (table_get_rows(table) > 1)
+ printf("\n%zu %s listed.\n", table_get_rows(table) - 1, word);
+ else
+ printf("No %s.\n", word);
+ }
+
+ return 0;
}
-static int list_images(int argc, char *argv[], void *userdata) {
+static int list_machines(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- size_t max_name = STRLEN("NAME"), max_type = STRLEN("TYPE"), max_size = STRLEN("USAGE"), max_crtime = STRLEN("CREATED"), max_mtime = STRLEN("MODIFIED");
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ ImageInfo *images = NULL;
- size_t n_images = 0, n_allocated = 0, j;
- const char *name, *type, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- uint64_t crtime, mtime, size;
- int read_only, r;
+ int r;
assert(bus);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
- "ListImages",
+ "ListMachines",
&error,
&reply,
- "");
- if (r < 0) {
- log_error("Could not get images: %s", bus_error_message(&error, -r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Could not get machines: %s", bus_error_message(&error, r));
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
+ table = table_new("MACHINE", "CLASS", "SERVICE", "OS", "VERSION", "ADDRESSES");
+ if (!table)
+ return log_oom();
+
+ r = sd_bus_message_enter_container(reply, 'a', "(ssso)");
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
- char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
- size_t l;
+ for (;;) {
+ _cleanup_free_ char *os = NULL, *version_id = NULL, *addresses = NULL;
+ const char *name, *class, *service;
+
+ r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
if (name[0] == '.' && !arg_all)
continue;
- if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
- return log_oom();
+ (void) call_get_os_release(
+ bus,
+ "GetMachineOSRelease",
+ name,
+ "ID\0"
+ "VERSION_ID\0",
+ &os,
+ &version_id);
- images[n_images].name = name;
- images[n_images].type = type;
- images[n_images].read_only = read_only;
- images[n_images].crtime = crtime;
- images[n_images].mtime = mtime;
- images[n_images].size = size;
+ (void) call_get_addresses(
+ bus,
+ name,
+ 0,
+ "",
+ "",
+ arg_addrs,
+ &addresses);
+
+ r = table_add_many(table,
+ TABLE_STRING, name,
+ TABLE_STRING, class,
+ TABLE_STRING, empty_to_dash(service),
+ TABLE_STRING, empty_to_dash(os),
+ TABLE_STRING, empty_to_dash(version_id),
+ TABLE_STRING, empty_to_dash(addresses));
+ if (r < 0)
+ return log_error_errno(r, "Failed to add table row: %m");
+ }
- l = strlen(name);
- if (l > max_name)
- max_name = l;
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
- l = strlen(type);
- if (l > max_type)
- max_type = l;
+ return show_table(table, "machines");
+}
- if (crtime != 0) {
- l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime)));
- if (l > max_crtime)
- max_crtime = l;
- }
+static int list_images(int argc, char *argv[], void *userdata) {
- if (mtime != 0) {
- l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime)));
- if (l > max_mtime)
- max_mtime = l;
- }
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(table_unrefp) Table *table = NULL;
+ sd_bus *bus = userdata;
+ int r;
- if (size != (uint64_t) -1) {
- l = strlen(strna(format_bytes(buf, sizeof(buf), size)));
- if (l > max_size)
- max_size = l;
- }
+ assert(bus);
- n_images++;
- }
+ (void) pager_open(arg_no_pager, false);
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "ListImages",
+ &error,
+ &reply,
+ NULL);
if (r < 0)
- return bus_log_parse_error(r);
+ return log_error_errno(r, "Could not get images: %s", bus_error_message(&error, r));
- r = sd_bus_message_exit_container(reply);
+ table = table_new("NAME", "TYPE", "RO", "USAGE", "CREATED", "MODIFIED");
+ if (!table)
+ return log_oom();
+
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(3), 100);
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
if (r < 0)
return bus_log_parse_error(r);
- qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info);
+ for (;;) {
+ uint64_t crtime, mtime, size;
+ const char *name, *type;
+ TableCell *cell;
+ bool ro_bool;
+ int ro_int;
- if (arg_legend && n_images > 0)
- printf("%-*s %-*s %-3s %-*s %-*s %-*s\n",
- (int) max_name, "NAME",
- (int) max_type, "TYPE",
- "RO",
- (int) max_size, "USAGE",
- (int) max_crtime, "CREATED",
- (int) max_mtime, "MODIFIED");
+ r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &ro_int, &crtime, &mtime, &size, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
- for (j = 0; j < n_images; j++) {
- char crtime_buf[FORMAT_TIMESTAMP_MAX], mtime_buf[FORMAT_TIMESTAMP_MAX], size_buf[FORMAT_BYTES_MAX];
+ if (name[0] == '.' && !arg_all)
+ continue;
- printf("%-*s %-*s %s%-3s%s %-*s %-*s %-*s\n",
- (int) max_name, images[j].name,
- (int) max_type, images[j].type,
- images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_normal() : "",
- (int) max_size, strna(format_bytes(size_buf, sizeof(size_buf), images[j].size)),
- (int) max_crtime, strna(format_timestamp(crtime_buf, sizeof(crtime_buf), images[j].crtime)),
- (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime)));
- }
+ r = table_add_many(table,
+ TABLE_STRING, name,
+ TABLE_STRING, type);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add table row: %m");
- if (arg_legend) {
- if (n_images > 0)
- printf("\n%zu images listed.\n", n_images);
- else
- printf("No images.\n");
+ ro_bool = ro_int;
+ r = table_add_cell(table, &cell, TABLE_BOOLEAN, &ro_bool);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add table cell: %m");
+
+ if (ro_bool) {
+ r = table_set_color(table, cell, ansi_highlight_red());
+ if (r < 0)
+ return log_error_errno(r, "Failed to set table cell color: %m");
+ }
+
+ r = table_add_many(table,
+ TABLE_SIZE, size,
+ TABLE_TIMESTAMP, crtime,
+ TABLE_TIMESTAMP, mtime);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add table row: %m");
}
- return 0;
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return show_table(table, "images");
}
static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
@@ -508,85 +468,17 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
}
static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2, int n_addr) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_free_ char *addresses = NULL;
- bool truncate = false;
- unsigned n = 0;
+ _cleanup_free_ char *s = NULL;
int r;
- assert(bus);
- assert(name);
- assert(prefix);
- assert(prefix2);
-
- r = sd_bus_call_method(bus,
- "org.freedesktop.machine1",
- "/org/freedesktop/machine1",
- "org.freedesktop.machine1.Manager",
- "GetMachineAddresses",
- NULL,
- &reply,
- "s", name);
+ r = call_get_addresses(bus, name, ifi, prefix, prefix2, n_addr, &s);
if (r < 0)
return r;
- addresses = strdup(prefix);
- if (!addresses)
- return log_oom();
- prefix = "";
+ if (r > 0)
+ fputs(s, stdout);
- r = sd_bus_message_enter_container(reply, 'a', "(iay)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
- int family;
- const void *a;
- size_t sz;
- char buf_ifi[DECIMAL_STR_MAX(int) + 2], buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
-
- r = sd_bus_message_read(reply, "i", &family);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read_array(reply, 'y', &a, &sz);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (n_addr != 0) {
- if (family == AF_INET6 && ifi > 0)
- xsprintf(buf_ifi, "%%%i", ifi);
- else
- strcpy(buf_ifi, "");
-
- if (!strextend(&addresses, prefix, inet_ntop(family, a, buffer, sizeof(buffer)), buf_ifi, NULL))
- return log_oom();
- } else
- truncate = true;
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (prefix != prefix2)
- prefix = prefix2;
-
- if (n_addr > 0)
- n_addr -= 1;
-
- n++;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (n > 0)
- fprintf(stdout, "%s%s", addresses, truncate ? "..." : "");
-
- return (int) n;
+ return r;
}
static int print_os_release(sd_bus *bus, const char *method, const char *name, const char *prefix) {
@@ -639,12 +531,12 @@ static int print_uid_shift(sd_bus *bus, const char *name) {
}
typedef struct MachineStatusInfo {
- char *name;
+ const char *name;
sd_id128_t id;
- char *class;
- char *service;
- char *unit;
- char *root_directory;
+ const char *class;
+ const char *service;
+ const char *unit;
+ const char *root_directory;
pid_t leader;
struct dual_timestamp timestamp;
int *netif;
@@ -653,19 +545,15 @@ typedef struct MachineStatusInfo {
static void machine_status_info_clear(MachineStatusInfo *info) {
if (info) {
- free(info->name);
- free(info->class);
- free(info->service);
- free(info->unit);
- free(info->root_directory);
free(info->netif);
zero(*info);
}
}
static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2;
int ifi = -1;
assert(bus);
@@ -803,6 +691,7 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(machine_status_info_clear) MachineStatusInfo info = {};
int r;
@@ -815,7 +704,9 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo
"org.freedesktop.machine1",
path,
map,
+ 0,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -841,7 +732,7 @@ static int show_machine_properties(sd_bus *bus, const char *path, bool *new_line
*new_line = true;
- r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_value, arg_all);
+ r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_value, arg_all, NULL);
if (r < 0)
log_error_errno(r, "Could not get properties: %m");
@@ -860,7 +751,7 @@ static int show_machine(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (properties && argc <= 1) {
@@ -994,10 +885,10 @@ static int print_image_machine_info(sd_bus *bus, const char *name) {
}
typedef struct ImageStatusInfo {
- char *name;
- char *path;
- char *type;
- int read_only;
+ const char *name;
+ const char *path;
+ const char *type;
+ bool read_only;
usec_t crtime;
usec_t mtime;
uint64_t usage;
@@ -1006,21 +897,12 @@ typedef struct ImageStatusInfo {
uint64_t limit_exclusive;
} ImageStatusInfo;
-static void image_status_info_clear(ImageStatusInfo *info) {
- if (!info)
- return;
-
- free(info->name);
- free(info->path);
- free(info->type);
- zero(*info);
-}
-
static void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
- char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2;
- char bs[FORMAT_BYTES_MAX], *s3;
- char bs_exclusive[FORMAT_BYTES_MAX], *s4;
+ char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char ts_absolute[FORMAT_TIMESTAMP_MAX];
+ char bs[FORMAT_BYTES_MAX];
+ char bs_exclusive[FORMAT_BYTES_MAX];
+ const char *s1, *s2, *s3, *s4;
assert(bus);
assert(i);
@@ -1093,7 +975,8 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) {
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(image_status_info_clear) ImageStatusInfo info = {};
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ ImageStatusInfo info = {};
int r;
assert(bus);
@@ -1104,7 +987,9 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) {
"org.freedesktop.machine1",
path,
map,
+ BUS_MAP_BOOLEAN_AS_BOOL,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -1119,20 +1004,11 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) {
}
typedef struct PoolStatusInfo {
- char *path;
+ const char *path;
uint64_t usage;
uint64_t limit;
} PoolStatusInfo;
-static void pool_status_info_clear(PoolStatusInfo *info) {
- if (info) {
- free(info->path);
- zero(*info);
- info->usage = -1;
- info->limit = -1;
- }
-}
-
static void print_pool_status_info(sd_bus *bus, PoolStatusInfo *i) {
char bs[FORMAT_BYTES_MAX], *s;
@@ -1157,12 +1033,13 @@ static int show_pool_info(sd_bus *bus) {
{}
};
- _cleanup_(pool_status_info_clear) PoolStatusInfo info = {
+ PoolStatusInfo info = {
.usage = (uint64_t) -1,
.limit = (uint64_t) -1,
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
@@ -1171,7 +1048,9 @@ static int show_pool_info(sd_bus *bus) {
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
map,
+ 0,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -1181,7 +1060,6 @@ static int show_pool_info(sd_bus *bus) {
return 0;
}
-
static int show_image_properties(sd_bus *bus, const char *path, bool *new_line) {
int r;
@@ -1194,7 +1072,7 @@ static int show_image_properties(sd_bus *bus, const char *path, bool *new_line)
*new_line = true;
- r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_value, arg_all);
+ r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_value, arg_all, NULL);
if (r < 0)
log_error_errno(r, "Could not get properties: %m");
@@ -1213,7 +1091,7 @@ static int show_image(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
@@ -1535,7 +1413,7 @@ static int login_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
int master = -1, r;
sd_bus *bus = userdata;
- const char *pty, *match, *machine;
+ const char *match, *machine;
assert(bus);
@@ -1586,7 +1464,7 @@ static int login_machine(int argc, char *argv[], void *userdata) {
return r;
}
- r = sd_bus_message_read(reply, "hs", &master, &pty);
+ r = sd_bus_message_read(reply, "hs", &master, NULL);
if (r < 0)
return bus_log_parse_error(r);
@@ -1601,7 +1479,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
int master = -1, r;
sd_bus *bus = userdata;
- const char *pty, *match, *machine, *path;
+ const char *match, *machine, *path;
_cleanup_free_ char *uid = NULL;
assert(bus);
@@ -1677,7 +1555,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
return r;
}
- r = sd_bus_message_read(reply, "hs", &master, &pty);
+ r = sd_bus_message_read(reply, "hs", &master, NULL);
if (r < 0)
return bus_log_parse_error(r);
@@ -1920,8 +1798,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
- int carries_install_info = 0;
+ size_t n_changes = 0;
const char *method = NULL;
sd_bus *bus = userdata;
int r, i;
@@ -1984,7 +1861,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
}
if (streq(argv[0], "enable")) {
- r = sd_bus_message_read(reply, "b", carries_install_info);
+ r = sd_bus_message_read(reply, "b", NULL);
if (r < 0)
return bus_log_parse_error(r);
}
@@ -2121,7 +1998,7 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
return r;
}
- r = sd_bus_message_read(reply, "uo", &id, &path);
+ r = sd_bus_message_read(reply, "uo", &id, NULL);
if (r < 0)
return bus_log_parse_error(r);
@@ -2537,13 +2414,13 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ TransferInfo *transfers = NULL;
size_t n_transfers = 0, n_allocated = 0, j;
- const char *type, *remote, *local, *object;
+ const char *type, *remote, *local;
sd_bus *bus = userdata;
uint32_t id, max_id = 0;
double progress;
int r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(bus,
"org.freedesktop.import1",
@@ -2562,7 +2439,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, &object)) > 0) {
+ while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, NULL)) > 0) {
size_t l;
if (!GREEDY_REALLOC(transfers, n_allocated, n_transfers + 1))
@@ -2666,12 +2543,14 @@ static int set_limit(int argc, char *argv[], void *userdata) {
uint64_t limit;
int r;
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
if (STR_IN_SET(argv[argc-1], "-", "none", "infinity"))
limit = (uint64_t) -1;
else {
r = parse_size(argv[argc-1], 1024, &limit);
if (r < 0)
- return log_error("Failed to parse size: %s", argv[argc-1]);
+ return log_error_errno(r, "Failed to parse size: %s", argv[argc-1]);
}
if (argc > 2)
@@ -2698,10 +2577,8 @@ static int set_limit(int argc, char *argv[], void *userdata) {
NULL,
"t", limit);
- if (r < 0) {
- log_error("Could not set limit: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not set limit: %s", bus_error_message(&error, r));
return 0;
}
@@ -2716,6 +2593,8 @@ static int clean_images(int argc, char *argv[], void *userdata) {
unsigned c = 0;
int r;
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
r = sd_bus_message_new_method_call(
bus,
&m,
@@ -2758,7 +2637,7 @@ static int clean_images(int argc, char *argv[], void *userdata) {
}
static int help(int argc, char *argv[], void *userdata) {
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the virtual machine and container\n"
@@ -2977,6 +2856,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
@@ -2997,7 +2881,12 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 's':
- arg_signal = signal_from_string_try_harder(optarg);
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
+ arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
return -EINVAL;
@@ -3031,6 +2920,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_VERIFY:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(import_verify, ImportVerify, _IMPORT_VERIFY_MAX);
+ return 0;
+ }
+
arg_verify = import_verify_from_string(optarg);
if (arg_verify < 0) {
log_error("Failed to parse --verify= setting: %s", optarg);
@@ -3167,7 +3061,7 @@ int main(int argc, char*argv[]) {
goto finish;
}
- sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
+ (void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
r = machinectl_main(argc, argv, bus);
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 2eb97ebed0..32c0b04283 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -46,20 +28,7 @@
#include "unit-name.h"
#include "user-util.h"
-static int property_get_pool_path(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", "/var/lib/machines");
-}
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_pool_path, "s", "/var/lib/machines");
static int property_get_pool_usage(
sd_bus *bus,
@@ -171,8 +140,8 @@ static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_erro
if (r < 0)
return r;
- r = image_find(name, NULL);
- if (r == 0)
+ r = image_find(IMAGE_MACHINE, name, NULL);
+ if (r == -ENOENT)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
if (r < 0)
return r;
@@ -476,14 +445,14 @@ static int method_register_machine(sd_bus_message *message, void *userdata, sd_b
return method_register_machine_internal(message, false, userdata, error);
}
-static int method_terminate_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
+static int redirect_method_to_machine(sd_bus_message *message, Manager *m, sd_bus_error *error, sd_bus_message_handler_t method) {
Machine *machine;
const char *name;
int r;
assert(message);
assert(m);
+ assert(method);
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
@@ -493,67 +462,23 @@ static int method_terminate_machine(sd_bus_message *message, void *userdata, sd_
if (!machine)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
- return bus_machine_method_terminate(message, machine, error);
+ return method(message, machine, error);
}
-static int method_kill_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return sd_bus_error_set_errno(error, r);
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
+static int method_terminate_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_terminate);
+}
- return bus_machine_method_kill(message, machine, error);
+static int method_kill_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_kill);
}
static int method_get_machine_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return sd_bus_error_set_errno(error, r);
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_get_addresses(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_addresses);
}
static int method_get_machine_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return sd_bus_error_set_errno(error, r);
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_get_os_release(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_os_release);
}
static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -571,7 +496,7 @@ static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_er
if (!images)
return -ENOMEM;
- r = image_discover(images);
+ r = image_discover(IMAGE_MACHINE, images);
if (r < 0)
return r;
@@ -610,152 +535,41 @@ static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_er
}
static int method_open_machine_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return sd_bus_error_set_errno(error, r);
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_open_pty(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_pty);
}
static int method_open_machine_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_open_login(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_login);
}
static int method_open_machine_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
-
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_open_shell(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_shell);
}
static int method_bind_mount_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_bind_mount(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_bind_mount);
}
static int method_copy_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_copy(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_copy);
}
static int method_open_machine_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_open_root_directory(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_root_directory);
}
static int method_get_machine_uid_shift(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
- Machine *machine;
- const char *name;
- int r;
-
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- machine = hashmap_get(m->machines, name);
- if (!machine)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
-
- return bus_machine_method_get_uid_shift(message, machine, error);
+ return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_uid_shift);
}
-static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int redirect_method_to_image(sd_bus_message *message, Manager *m, sd_bus_error *error, sd_bus_message_handler_t method) {
_cleanup_(image_unrefp) Image* i = NULL;
const char *name;
int r;
assert(message);
+ assert(m);
+ assert(method);
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
@@ -764,182 +578,46 @@ static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_e
if (!image_name_is_valid(name))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
- r = image_find(name, &i);
- if (r < 0)
- return r;
- if (r == 0)
+ r = image_find(IMAGE_MACHINE, name, &i);
+ if (r == -ENOENT)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
-
- i->userdata = userdata;
- return bus_image_method_remove(message, i, error);
-}
-
-static int method_rename_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(image_unrefp) Image* i = NULL;
- const char *old_name;
- int r;
-
- assert(message);
-
- r = sd_bus_message_read(message, "s", &old_name);
if (r < 0)
return r;
- if (!image_name_is_valid(old_name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
+ i->userdata = m;
+ return method(message, i, error);
+}
- r = image_find(old_name, &i);
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
+static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(message, userdata, error, bus_image_method_remove);
+}
- i->userdata = userdata;
- return bus_image_method_rename(message, i, error);
+static int method_rename_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(message, userdata, error, bus_image_method_rename);
}
static int method_clone_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(image_unrefp) Image *i = NULL;
- const char *old_name;
- int r;
-
- assert(message);
-
- r = sd_bus_message_read(message, "s", &old_name);
- if (r < 0)
- return r;
-
- if (!image_name_is_valid(old_name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
-
- r = image_find(old_name, &i);
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
-
- i->userdata = userdata;
- return bus_image_method_clone(message, i, error);
+ return redirect_method_to_image(message, userdata, error, bus_image_method_clone);
}
static int method_mark_image_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(image_unrefp) Image *i = NULL;
- const char *name;
- int r;
-
- assert(message);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- if (!image_name_is_valid(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
-
- r = image_find(name, &i);
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
-
- i->userdata = userdata;
- return bus_image_method_mark_read_only(message, i, error);
+ return redirect_method_to_image(message, userdata, error, bus_image_method_mark_read_only);
}
static int method_get_image_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(image_unrefp) Image *i = NULL;
- const char *name;
- int r;
-
- assert(message);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- if (!image_name_is_valid(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
-
- r = image_find(name, &i);
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
-
- i->userdata = userdata;
- return bus_image_method_get_hostname(message, i, error);
+ return redirect_method_to_image(message, userdata, error, bus_image_method_get_hostname);
}
static int method_get_image_machine_id(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(image_unrefp) Image *i = NULL;
- const char *name;
- int r;
-
- assert(message);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- if (!image_name_is_valid(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
-
- r = image_find(name, &i);
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
-
- i->userdata = userdata;
- return bus_image_method_get_machine_id(message, i, error);
+ return redirect_method_to_image(message, userdata, error, bus_image_method_get_machine_id);
}
static int method_get_image_machine_info(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(image_unrefp) Image *i = NULL;
- const char *name;
- int r;
-
- assert(message);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- if (!image_name_is_valid(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
-
- r = image_find(name, &i);
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
-
- i->userdata = userdata;
- return bus_image_method_get_machine_info(message, i, error);
+ return redirect_method_to_image(message, userdata, error, bus_image_method_get_machine_info);
}
static int method_get_image_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(image_unrefp) Image *i = NULL;
- const char *name;
- int r;
-
- assert(message);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- if (!image_name_is_valid(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
-
- r = image_find(name, &i);
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
-
- i->userdata = userdata;
- return bus_image_method_get_os_release(message, i, error);
+ return redirect_method_to_image(message, userdata, error, bus_image_method_get_os_release);
}
static int clean_pool_done(Operation *operation, int ret, sd_bus_error *error) {
@@ -1096,7 +774,7 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err
goto child_fail;
}
- r = image_discover(images);
+ r = image_discover(IMAGE_MACHINE, images);
if (r < 0)
goto child_fail;
@@ -1224,27 +902,7 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
}
static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(image_unrefp) Image *i = NULL;
- const char *name;
- int r;
-
- assert(message);
-
- r = sd_bus_message_read(message, "s", &name);
- if (r < 0)
- return r;
-
- if (!image_name_is_valid(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
-
- r = image_find(name, &i);
- if (r < 0)
- return r;
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
-
- i->userdata = userdata;
- return bus_image_method_set_limit(message, i, error);
+ return redirect_method_to_image(message, userdata, error, bus_image_method_set_limit);
}
static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -1347,6 +1005,10 @@ static int method_map_to_machine_user(sd_bus_message *message, void *userdata, s
return -EIO;
}
+ /* The private user namespace is disabled, ignoring. */
+ if (uid_shift == 0)
+ continue;
+
if (uid < uid_shift || uid >= uid_shift + uid_range)
continue;
@@ -1465,6 +1127,10 @@ static int method_map_to_machine_group(sd_bus_message *message, void *groupdata,
return -EIO;
}
+ /* The private user namespace is disabled, ignoring. */
+ if (gid_shift == 0)
+ continue;
+
if (gid < gid_shift || gid >= gid_shift + gid_range)
continue;
@@ -1925,30 +1591,3 @@ int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
return 0;
}
-
-int bus_reply_pair_array(sd_bus_message *m, char **l) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- char **k, **v;
- int r;
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(reply, 'a', "{ss}");
- if (r < 0)
- return r;
-
- STRV_FOREACH_PAIR(k, v, l) {
- r = sd_bus_message_append(reply, "{ss}", *k, *v);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- return sd_bus_send(NULL, reply, NULL);
-
-}
diff --git a/src/machine/machined.c b/src/machine/machined.c
index 9fb67882e1..a6f0d847d5 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -39,38 +21,49 @@
#include "signal-util.h"
#include "special.h"
-Manager *manager_new(void) {
- Manager *m;
+static Manager* manager_unref(Manager *m);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
+
+static int manager_new(Manager **ret) {
+ _cleanup_(manager_unrefp) Manager *m = NULL;
int r;
+ assert(ret);
+
m = new0(Manager, 1);
if (!m)
- return NULL;
+ return -ENOMEM;
m->machines = hashmap_new(&string_hash_ops);
m->machine_units = hashmap_new(&string_hash_ops);
m->machine_leaders = hashmap_new(NULL);
- if (!m->machines || !m->machine_units || !m->machine_leaders) {
- manager_free(m);
- return NULL;
- }
+ if (!m->machines || !m->machine_units || !m->machine_leaders)
+ return -ENOMEM;
r = sd_event_default(&m->event);
- if (r < 0) {
- manager_free(m);
- return NULL;
- }
+ if (r < 0)
+ return r;
- sd_event_set_watchdog(m->event, true);
+ r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
+ if (r < 0)
+ return r;
- return m;
+ r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ (void) sd_event_set_watchdog(m->event, true);
+
+ *ret = TAKE_PTR(m);
+ return 0;
}
-void manager_free(Manager *m) {
+static Manager* manager_unref(Manager *m) {
Machine *machine;
- assert(m);
+ if (!m)
+ return NULL;
while (m->operations)
operation_free(m->operations);
@@ -93,7 +86,7 @@ void manager_free(Manager *m) {
sd_bus_unref(m->bus);
sd_event_unref(m->event);
- free(m);
+ return mfree(m);
}
static int manager_add_host_machine(Manager *m) {
@@ -124,9 +117,8 @@ static int manager_add_host_machine(Manager *m) {
t->leader = 1;
t->id = mid;
- t->root_directory = rd;
- t->unit = unit;
- rd = unit = NULL;
+ t->root_directory = TAKE_PTR(rd);
+ t->unit = TAKE_PTR(unit);
dual_timestamp_from_boottime_or_monotonic(&t->timestamp, 0);
@@ -135,7 +127,7 @@ static int manager_add_host_machine(Manager *m) {
return 0;
}
-int manager_enumerate_machines(Manager *m) {
+static int manager_enumerate_machines(Manager *m) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
@@ -282,7 +274,7 @@ static int manager_connect_bus(Manager *m) {
return 0;
}
-void manager_gc(Manager *m, bool drop_not_started) {
+static void manager_gc(Manager *m, bool drop_not_started) {
Machine *machine;
assert(m);
@@ -306,7 +298,7 @@ void manager_gc(Manager *m, bool drop_not_started) {
}
}
-int manager_startup(Manager *m) {
+static int manager_startup(Manager *m) {
Machine *machine;
Iterator i;
int r;
@@ -342,7 +334,7 @@ static bool check_idle(void *userdata) {
return hashmap_isempty(m->machines);
}
-int manager_run(Manager *m) {
+static int manager_run(Manager *m) {
assert(m);
return bus_event_loop_with_idle(
@@ -354,7 +346,7 @@ int manager_run(Manager *m) {
}
int main(int argc, char *argv[]) {
- Manager *m = NULL;
+ _cleanup_(manager_unrefp) Manager *m = NULL;
int r;
log_set_target(LOG_TARGET_AUTO);
@@ -370,18 +362,16 @@ int main(int argc, char *argv[]) {
goto finish;
}
- /* Always create the directories people can create inotify
- * watches in. Note that some applications might check for the
- * existence of /run/systemd/machines/ to determine whether
- * machined is available, so please always make sure this
- * check stays in. */
- mkdir_label("/run/systemd/machines", 0755);
+ /* Always create the directories people can create inotify watches in. Note that some applications might check
+ * for the existence of /run/systemd/machines/ to determine whether machined is available, so please always
+ * make sure this check stays in. */
+ (void) mkdir_label("/run/systemd/machines", 0755);
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, -1) >= 0);
- m = manager_new();
- if (!m) {
- r = log_oom();
+ r = manager_new(&m);
+ if (r < 0) {
+ log_error_errno(r, "Failed to allocate manager object: %m");
goto finish;
}
@@ -393,16 +383,18 @@ int main(int argc, char *argv[]) {
log_debug("systemd-machined running as pid "PID_FMT, getpid_cached());
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
+ (void) sd_notify(false,
+ "READY=1\n"
+ "STATUS=Processing requests...");
r = manager_run(m);
log_debug("systemd-machined stopped as pid "PID_FMT, getpid_cached());
-finish:
- manager_free(m);
+ (void) sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down...");
+finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/machine/machined.h b/src/machine/machined.h
index b00c4c182e..3197c1aade 100644
--- a/src/machine/machined.h
+++ b/src/machine/machined.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "sd-bus.h"
@@ -56,17 +37,7 @@ struct Manager {
unsigned n_operations;
};
-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 sd_bus_vtable manager_vtable[];
diff --git a/src/machine/meson.build b/src/machine/meson.build
index b530ca6377..d515877138 100644
--- a/src/machine/meson.build
+++ b/src/machine/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
systemd_machined_sources = files('''
machined.c
diff --git a/src/machine/operation.c b/src/machine/operation.c
index 6aba1a2af4..42c51f3654 100644
--- a/src/machine/operation.c
+++ b/src/machine/operation.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/wait.h>
diff --git a/src/machine/operation.h b/src/machine/operation.h
index 361bf1fb44..0e3302856f 100644
--- a/src/machine/operation.h
+++ b/src/machine/operation.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/types.h>
#include "sd-bus.h"
diff --git a/src/machine/test-machine-tables.c b/src/machine/test-machine-tables.c
index fc08785f14..04db7d8259 100644
--- a/src/machine/test-machine-tables.c
+++ b/src/machine/test-machine-tables.c
@@ -1,30 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "machine.h"
#include "test-tables.h"
int main(int argc, char **argv) {
+ test_table(kill_who, KILL_WHO);
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/modules-load/modules-load.c b/src/modules-load/modules-load.c
index c5f57685a2..c49a6b7a76 100644
--- a/src/modules-load/modules-load.c
+++ b/src/modules-load/modules-load.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c
index 0cd9f07094..64c1efdb1c 100644
--- a/src/mount/mount-tool.c
+++ b/src/mount/mount-tool.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
@@ -367,7 +349,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!arg_mount_what)
return log_oom();
- path_kill_slashes(arg_mount_what);
+ path_simplify(arg_mount_what, false);
if (!path_is_absolute(arg_mount_what)) {
log_error("Only absolute path is supported: %s", arg_mount_what);
@@ -385,7 +367,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!arg_mount_where)
return log_oom();
- path_kill_slashes(arg_mount_where);
+ path_simplify(arg_mount_where, false);
if (!path_is_absolute(arg_mount_where)) {
log_error("Only absolute path is supported: %s", arg_mount_where);
@@ -467,7 +449,7 @@ static int transient_mount_set_properties(sd_bus_message *m) {
r = asprintf(&options,
"uid=" UID_FMT ",gid=" GID_FMT "%s%s",
arg_uid, arg_gid,
- arg_mount_options ? "," : "", arg_mount_options);
+ arg_mount_options ? "," : "", strempty(arg_mount_options));
if (r < 0)
return -ENOMEM;
}
@@ -766,16 +748,14 @@ static int find_mount_points(const char *what, char ***list) {
if (!GREEDY_REALLOC(l, bufsize, n + 2))
return log_oom();
- l[n++] = where;
- where = NULL;
+ l[n++] = TAKE_PTR(where);
}
if (!GREEDY_REALLOC(l, bufsize, n + 1))
return log_oom();
l[n] = NULL;
- *list = l;
- l = NULL; /* avoid freeing */
+ *list = TAKE_PTR(l);
return n;
}
@@ -827,8 +807,7 @@ static int find_loop_device(const char *backing_file, char **loop_dev) {
if (!l)
return -ENXIO;
- *loop_dev = l;
- l = NULL; /* avoid freeing */
+ *loop_dev = TAKE_PTR(l);
return 0;
}
@@ -931,8 +910,8 @@ static int stop_mounts(
}
static int umount_by_device(sd_bus *bus, const char *what) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
_cleanup_strv_free_ char **list = NULL;
struct stat st;
const char *v;
@@ -1008,7 +987,7 @@ static int action_umount(
if (!p)
return log_oom();
- path_kill_slashes(p);
+ path_simplify(p, false);
r = stop_mounts(bus, p);
if (r < 0)
@@ -1253,8 +1232,8 @@ static int acquire_removable(struct udev_device *d) {
}
static int discover_loop_backing_file(void) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
_cleanup_free_ char *loop_dev = NULL;
struct stat st;
const char *v;
@@ -1328,8 +1307,8 @@ static int discover_loop_backing_file(void) {
}
static int discover_device(void) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
struct stat st;
const char *v;
int r;
@@ -1422,8 +1401,8 @@ static int list_devices(void) {
[COLUMN_UUID] = "UUID"
};
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
size_t n_allocated = 0, n = 0, i;
size_t column_width[_COLUMN_MAX];
@@ -1456,7 +1435,7 @@ static int list_devices(void) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d;
+ _cleanup_(udev_device_unrefp) struct udev_device *d;
struct item *j;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
@@ -1529,7 +1508,7 @@ static int list_devices(void) {
qsort_safe(items, n, sizeof(struct item), compare_item);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
fputs(ansi_underline(), stdout);
for (c = 0; c < _COLUMN_MAX; c++) {
diff --git a/src/network/meson.build b/src/network/meson.build
index e1ac0f13dc..8f5544ea04 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
sources = files('''
netdev/bond.c
@@ -48,6 +33,8 @@ sources = files('''
netdev/vxcan.h
netdev/wireguard.c
netdev/wireguard.h
+ netdev/netdevsim.c
+ netdev/netdevsim.h
networkd-address-label.c
networkd-address-label.h
networkd-address-pool.c
diff --git a/src/network/netdev/bond.c b/src/network/netdev/bond.c
index f6c9cebda3..5840a966ab 100644
--- a/src/network/netdev/bond.c
+++ b/src/network/netdev/bond.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
- Copyright 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/ether.h>
#include <linux/if_bonding.h>
diff --git a/src/network/netdev/bond.h b/src/network/netdev/bond.h
index 31be5b83a3..fd68a18985 100644
--- a/src/network/netdev/bond.h
+++ b/src/network/netdev/bond.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "in-addr-util.h"
#include "list.h"
diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c
index 00d4d30a67..be5914a2fa 100644
--- a/src/network/netdev/bridge.c
+++ b/src/network/netdev/bridge.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
- Copyright 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
@@ -29,7 +10,7 @@
/* callback for brige netdev's parameter set */
static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_netdev_unref_ NetDev *netdev = userdata;
+ _cleanup_(netdev_unrefp) NetDev *netdev = userdata;
int r;
assert(netdev);
diff --git a/src/network/netdev/bridge.h b/src/network/netdev/bridge.h
index 7fc993bb8d..4854e46953 100644
--- a/src/network/netdev/bridge.h
+++ b/src/network/netdev/bridge.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "netdev/netdev.h"
diff --git a/src/network/netdev/dummy.c b/src/network/netdev/dummy.c
index c55009092a..aded1c589f 100644
--- a/src/network/netdev/dummy.c
+++ b/src/network/netdev/dummy.c
@@ -1,24 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Susant Sahani <susant@redhat.com>
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "netdev/dummy.h"
diff --git a/src/network/netdev/dummy.h b/src/network/netdev/dummy.h
index abfb7c71ef..f4679a640d 100644
--- a/src/network/netdev/dummy.h
+++ b/src/network/netdev/dummy.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "netdev/netdev.h"
diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c
index 1d50963e04..18b6b359f3 100644
--- a/src/network/netdev/geneve.c
+++ b/src/network/netdev/geneve.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
@@ -36,7 +18,7 @@
/* callback for geneve netdev's created without a backing Link */
static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_netdev_unref_ NetDev *netdev = userdata;
+ _cleanup_(netdev_unrefp) NetDev *netdev = userdata;
int r;
assert(netdev->state != _NETDEV_STATE_INVALID);
@@ -79,7 +61,7 @@ static int netdev_geneve_create(NetDev *netdev) {
return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");
}
- if (netdev->mtu) {
+ if (netdev->mtu != 0) {
r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m");
@@ -163,7 +145,6 @@ static int netdev_geneve_create(NetDev *netdev) {
log_netdev_debug(netdev, "Creating");
-
return r;
}
diff --git a/src/network/netdev/geneve.h b/src/network/netdev/geneve.h
index 9aec8f505b..dab9a4a553 100644
--- a/src/network/netdev/geneve.h
+++ b/src/network/netdev/geneve.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 Geneve Geneve;
diff --git a/src/network/netdev/ipvlan.c b/src/network/netdev/ipvlan.c
index 856f5bd805..5bb6a5bb35 100644
--- a/src/network/netdev/ipvlan.c
+++ b/src/network/netdev/ipvlan.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013-2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
diff --git a/src/network/netdev/ipvlan.h b/src/network/netdev/ipvlan.h
index b6bc1ac739..8b698ebd1a 100644
--- a/src/network/netdev/ipvlan.h
+++ b/src/network/netdev/ipvlan.h
@@ -1,31 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014-2015 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/if_link.h>
#include "missing.h"
#include "netdev/netdev.h"
-
typedef enum IPVlanMode {
NETDEV_IPVLAN_MODE_L2 = IPVLAN_MODE_L2,
NETDEV_IPVLAN_MODE_L3 = IPVLAN_MODE_L3,
diff --git a/src/network/netdev/macvlan.c b/src/network/netdev/macvlan.c
index 9924e16055..871f0201a8 100644
--- a/src/network/netdev/macvlan.c
+++ b/src/network/netdev/macvlan.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
diff --git a/src/network/netdev/macvlan.h b/src/network/netdev/macvlan.h
index 7d6d346438..dcc0a3fd35 100644
--- a/src/network/netdev/macvlan.h
+++ b/src/network/netdev/macvlan.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 MacVlan MacVlan;
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index ba6268fa66..dfcac9adbf 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -40,7 +40,7 @@ Match.Architecture, config_parse_net_condition, CONDITI
NetDev.Description, config_parse_string, 0, offsetof(NetDev, description)
NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname)
NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind)
-NetDev.MTUBytes, config_parse_iec_size, 0, offsetof(NetDev, mtu)
+NetDev.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(NetDev, mtu)
NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac)
VLAN.Id, config_parse_vlanid, 0, offsetof(VLan, id)
VLAN.GVRP, config_parse_tristate, 0, offsetof(VLan, gvrp)
@@ -50,7 +50,7 @@ VLAN.ReorderHeader, config_parse_tristate, 0,
MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
-IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
+IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
Tunnel.Local, config_parse_tunnel_address, 0, offsetof(Tunnel, local)
Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote)
Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos)
@@ -145,7 +145,7 @@ Bridge.MulticastSnooping, config_parse_tristate, 0,
Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering)
Bridge.STP, config_parse_tristate, 0, offsetof(Bridge, stp)
VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table) /* deprecated */
-VRF.Table, config_parse_route_table, 0, offsetof(Vrf, table)
+VRF.Table, config_parse_uint32, 0, offsetof(Vrf, table)
WireGuard.FwMark, config_parse_unsigned, 0, offsetof(Wireguard, fwmark)
WireGuard.ListenPort, config_parse_wireguard_listen_port, 0, offsetof(Wireguard, port)
WireGuard.PrivateKey, config_parse_wireguard_private_key, 0, 0
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index fa054fcfc3..82ce88402f 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
@@ -50,6 +32,7 @@
#include "netdev/vcan.h"
#include "netdev/vxcan.h"
#include "netdev/wireguard.h"
+#include "netdev/netdevsim.h"
const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_BRIDGE] = &bridge_vtable,
@@ -77,6 +60,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_GENEVE] = &geneve_vtable,
[NETDEV_KIND_VXCAN] = &vxcan_vtable,
[NETDEV_KIND_WIREGUARD] = &wireguard_vtable,
+ [NETDEV_KIND_NETDEVSIM] = &netdevsim_vtable,
};
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -105,6 +89,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_GENEVE] = "geneve",
[NETDEV_KIND_VXCAN] = "vxcan",
[NETDEV_KIND_WIREGUARD] = "wireguard",
+ [NETDEV_KIND_NETDEVSIM] = "netdevsim",
};
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
@@ -255,7 +240,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_h
r = sd_netlink_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
if (r < 0)
- return log_netdev_error(netdev, "Could not send rtnetlink message: %m");
+ return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
link_ref(link);
@@ -298,7 +283,7 @@ static int netdev_enter_ready(NetDev *netdev) {
/* callback for netdev's created without a backing Link */
static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_netdev_unref_ NetDev *netdev = userdata;
+ _cleanup_(netdev_unrefp) NetDev *netdev = userdata;
int r;
assert(netdev->state != _NETDEV_STATE_INVALID);
@@ -488,8 +473,7 @@ int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
- *ret = mac;
- mac = NULL;
+ *ret = TAKE_PTR(mac);
return 0;
}
@@ -613,7 +597,7 @@ int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t callbac
}
static int netdev_load_one(Manager *manager, const char *filename) {
- _cleanup_netdev_unref_ NetDev *netdev_raw = NULL, *netdev = NULL;
+ _cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL;
_cleanup_fclose_ FILE *file = NULL;
const char *dropin_dirname;
bool independent = false;
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index 51b3ea7a8f..8df26c0ac3 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-netlink.h"
@@ -61,6 +43,7 @@ typedef enum NetDevKind {
NETDEV_KIND_GENEVE,
NETDEV_KIND_VXCAN,
NETDEV_KIND_WIREGUARD,
+ NETDEV_KIND_NETDEVSIM,
_NETDEV_KIND_MAX,
_NETDEV_KIND_INVALID = -1
} NetDevKind;
@@ -104,7 +87,7 @@ typedef struct NetDev {
char *description;
char *ifname;
struct ether_addr *mac;
- size_t mtu;
+ uint32_t mtu;
int ifindex;
LIST_HEAD(netdev_join_callback, callbacks);
@@ -169,7 +152,6 @@ NetDev *netdev_unref(NetDev *netdev);
NetDev *netdev_ref(NetDev *netdev);
DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
-#define _cleanup_netdev_unref_ _cleanup_(netdev_unrefp)
int netdev_get(Manager *manager, const char *name, NetDev **ret);
int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
diff --git a/src/network/netdev/netdevsim.c b/src/network/netdev/netdevsim.c
new file mode 100644
index 0000000000..8caba67600
--- /dev/null
+++ b/src/network/netdev/netdevsim.c
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "netdev/netdevsim.h"
+#include "missing.h"
+
+const NetDevVTable netdevsim_vtable = {
+ .object_size = sizeof(NetDevSim),
+ .sections = "Match\0NetDev\0",
+ .create_type = NETDEV_CREATE_INDEPENDENT,
+};
diff --git a/src/network/netdev/netdevsim.h b/src/network/netdev/netdevsim.h
new file mode 100644
index 0000000000..7287360f15
--- /dev/null
+++ b/src/network/netdev/netdevsim.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+
+typedef struct NetDevSim NetDevSim;
+
+#include "netdev/netdev.h"
+
+struct NetDevSim {
+ NetDev meta;
+};
+
+DEFINE_NETDEV_CAST(NETDEVSIM, NetDevSim);
+extern const NetDevVTable netdevsim_vtable;
diff --git a/src/network/netdev/tunnel.c b/src/network/netdev/tunnel.c
index a6a3c701f9..c15ca74717 100644
--- a/src/network/netdev/tunnel.c
+++ b/src/network/netdev/tunnel.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <net/if.h>
@@ -414,10 +396,10 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
return -EINVAL;
}
- if (netdev->kind == NETDEV_KIND_VTI &&
+ if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_IPIP, NETDEV_KIND_GRE, NETDEV_KIND_GRETAP) &&
(t->family != AF_INET || in_addr_is_null(t->family, &t->local))) {
log_netdev_error(netdev,
- "vti tunnel without a local IPv4 address configured in %s. Ignoring", filename);
+ "vti/ipip/gre/gretap tunnel without a local IPv4 address configured in %s. Ignoring", filename);
return -EINVAL;
}
diff --git a/src/network/netdev/tunnel.h b/src/network/netdev/tunnel.h
index 7ffafe9e98..b54b58ddee 100644
--- a/src/network/netdev/tunnel.h
+++ b/src/network/netdev/tunnel.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "in-addr-util.h"
diff --git a/src/network/netdev/tuntap.c b/src/network/netdev/tuntap.c
index 4fc9b610af..21fb7ab067 100644
--- a/src/network/netdev/tuntap.c
+++ b/src/network/netdev/tuntap.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Susant Sahani <susant@redhat.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -157,7 +139,7 @@ static void tuntap_done(NetDev *netdev) {
static int tuntap_verify(NetDev *netdev, const char *filename) {
assert(netdev);
- if (netdev->mtu)
+ if (netdev->mtu != 0)
log_netdev_warning(netdev, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
if (netdev->mac)
diff --git a/src/network/netdev/tuntap.h b/src/network/netdev/tuntap.h
index dbfa3de180..6e8c66a000 100644
--- a/src/network/netdev/tuntap.h
+++ b/src/network/netdev/tuntap.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 TunTap TunTap;
diff --git a/src/network/netdev/vcan.c b/src/network/netdev/vcan.c
index 780cf91143..f06ad0fb42 100644
--- a/src/network/netdev/vcan.c
+++ b/src/network/netdev/vcan.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "netdev/vcan.h"
diff --git a/src/network/netdev/vcan.h b/src/network/netdev/vcan.h
index 6c4d68e694..d2540645c8 100644
--- a/src/network/netdev/vcan.h
+++ b/src/network/netdev/vcan.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 VCan VCan;
diff --git a/src/network/netdev/veth.c b/src/network/netdev/veth.c
index 2a2f50e345..3ad95ade0f 100644
--- a/src/network/netdev/veth.c
+++ b/src/network/netdev/veth.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Susant Sahani <susant@redhat.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <linux/veth.h>
diff --git a/src/network/netdev/veth.h b/src/network/netdev/veth.h
index bb2139ff57..29cddab573 100644
--- a/src/network/netdev/veth.h
+++ b/src/network/netdev/veth.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 Veth Veth;
diff --git a/src/network/netdev/vlan.c b/src/network/netdev/vlan.c
index e7c0e7602a..dd548b338a 100644
--- a/src/network/netdev/vlan.c
+++ b/src/network/netdev/vlan.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <linux/if_vlan.h>
diff --git a/src/network/netdev/vlan.h b/src/network/netdev/vlan.h
index c4688d9b13..f3629f903b 100644
--- a/src/network/netdev/vlan.h
+++ b/src/network/netdev/vlan.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 VLan VLan;
diff --git a/src/network/netdev/vrf.c b/src/network/netdev/vrf.c
index 5e04bbd272..f341061344 100644
--- a/src/network/netdev/vrf.c
+++ b/src/network/netdev/vrf.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2016 Andreas Rammhold <andreas@rammhold.de>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Andreas Rammhold <andreas@rammhold.de>
***/
#include <net/if.h>
diff --git a/src/network/netdev/vrf.h b/src/network/netdev/vrf.h
index 58f4ef30a4..d1ac6f6976 100644
--- a/src/network/netdev/vrf.h
+++ b/src/network/netdev/vrf.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2016 Andreas Rammhold <andreas@rammhold.de>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Andreas Rammhold <andreas@rammhold.de>
***/
typedef struct Vrf Vrf;
diff --git a/src/network/netdev/vxcan.c b/src/network/netdev/vxcan.c
index a41ca7e256..f8139b52c3 100644
--- a/src/network/netdev/vxcan.c
+++ b/src/network/netdev/vxcan.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "netdev/vxcan.h"
#include "missing.h"
diff --git a/src/network/netdev/vxcan.h b/src/network/netdev/vxcan.h
index f37213513f..84a39ee3cb 100644
--- a/src/network/netdev/vxcan.h
+++ b/src/network/netdev/vxcan.h
@@ -1,23 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 VxCan VxCan;
diff --git a/src/network/netdev/vxlan.c b/src/network/netdev/vxlan.c
index c9fd931718..e23dd13648 100644
--- a/src/network/netdev/vxlan.c
+++ b/src/network/netdev/vxlan.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
diff --git a/src/network/netdev/vxlan.h b/src/network/netdev/vxlan.h
index 3bb8884380..e5eb20f187 100644
--- a/src/network/netdev/vxlan.h
+++ b/src/network/netdev/vxlan.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 VxLan VxLan;
diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c
index f1f4bab475..fb91997f7a 100644
--- a/src/network/netdev/wireguard.c
+++ b/src/network/netdev/wireguard.c
@@ -1,21 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2016-2017 Jörg Thalheim <joerg@thalheim.io>
- Copyright 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016-2017 Jörg Thalheim <joerg@thalheim.io>
+ Copyright © 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
***/
#include <sys/ioctl.h>
@@ -228,8 +214,7 @@ static int on_resolve_retry(sd_event_source *s, usec_t usec, void *userdata) {
w->resolve_retry_event_source = sd_event_source_unref(w->resolve_retry_event_source);
- w->unresolved_endpoints = w->failed_endpoints;
- w->failed_endpoints = NULL;
+ w->unresolved_endpoints = TAKE_PTR(w->failed_endpoints);
resolve_endpoints(netdev);
@@ -328,7 +313,6 @@ static void resolve_endpoints(NetDev *netdev) {
}
}
-
static int netdev_wireguard_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
Wireguard *w;
@@ -468,7 +452,6 @@ int config_parse_wireguard_preshared_key(const char *unit,
peer->preshared_key);
}
-
int config_parse_wireguard_public_key(const char *unit,
const char *filename,
unsigned line,
@@ -627,15 +610,11 @@ int config_parse_wireguard_endpoint(const char *unit,
if (!port)
return log_oom();
- endpoint->peer = peer;
- endpoint->host = host;
- endpoint->port = port;
+ endpoint->peer = TAKE_PTR(peer);
+ endpoint->host = TAKE_PTR(host);
+ endpoint->port = TAKE_PTR(port);
endpoint->netdev = netdev_ref(data);
LIST_PREPEND(endpoints, w->unresolved_endpoints, endpoint);
-
- peer = NULL;
- host = NULL;
- port = NULL;
endpoint = NULL;
return 0;
diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h
index f788fa4221..6fdbf09a7e 100644
--- a/src/network/netdev/wireguard.h
+++ b/src/network/netdev/wireguard.h
@@ -1,22 +1,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2016 Jörg Thalheim <joerg@thalheim.io>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Jörg Thalheim <joerg@thalheim.io>
***/
typedef struct Wireguard Wireguard;
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 14d8ecb03f..3ab06f28e9 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
#include <linux/if_addrlabel.h>
@@ -210,8 +192,7 @@ static int acquire_link_info_strv(sd_netlink *rtnl, char **l, LinkInfo **ret) {
qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
- *ret = links;
- links = NULL;
+ *ret = TAKE_PTR(links);
return (int) c;
}
@@ -251,8 +232,7 @@ static int acquire_link_info_all(sd_netlink *rtnl, LinkInfo **ret) {
qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
- *ret = links;
- links = NULL;
+ *ret = TAKE_PTR(links);
return (int) c;
}
@@ -273,7 +253,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
if (c < 0)
return c;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (arg_legend)
printf("%3s %-16s %-18s %-11s %-10s\n",
@@ -651,6 +631,10 @@ static int next_lldp_neighbor(FILE *f, sd_lldp_neighbor **ret) {
if (l != sizeof(u))
return -EBADMSG;
+ /* each LLDP packet is at most MTU size, but let's allow up to 4KiB just in case */
+ if (le64toh(u) >= 4096)
+ return -EBADMSG;
+
raw = new(uint8_t, le64toh(u));
if (!raw)
return -ENOMEM;
@@ -836,7 +820,7 @@ static int link_status_one(
}
if (info->has_mtu)
- printf(" MTU: %u\n", info->mtu);
+ printf(" MTU: %" PRIu32 "\n", info->mtu);
(void) dump_addresses(rtnl, " Address: ", info->ifindex);
(void) dump_gateways(rtnl, hwdb, " Gateway: ", info->ifindex);
@@ -897,7 +881,7 @@ static int link_status(int argc, char *argv[], void *userdata) {
_cleanup_free_ LinkInfo *links = NULL;
int r, c, i;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_netlink_open(&rtnl);
if (r < 0)
@@ -993,7 +977,7 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
if (c < 0)
return c;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (arg_legend)
printf("%-16s %-17s %-16s %-11s %-17s %-16s\n",
@@ -1156,11 +1140,11 @@ static int parse_argv(int argc, char *argv[]) {
}
static int networkctl_main(int argc, char *argv[]) {
- const Verb verbs[] = {
- { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
- { "status", VERB_ANY, VERB_ANY, 0, link_status },
- { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
- { "label", VERB_ANY, VERB_ANY, 0, list_address_labels},
+ static const Verb verbs[] = {
+ { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
+ { "status", VERB_ANY, VERB_ANY, 0, link_status },
+ { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
+ { "label", VERB_ANY, VERB_ANY, 0, list_address_labels },
{}
};
diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c
index 4fd5fa4f58..4c55442739 100644
--- a/src/network/networkd-address-label.c
+++ b/src/network/networkd-address-label.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
#include <linux/if_addrlabel.h>
@@ -30,14 +12,13 @@
#include "socket-util.h"
int address_label_new(AddressLabel **ret) {
- _cleanup_address_label_free_ AddressLabel *addrlabel = NULL;
+ _cleanup_(address_label_freep) AddressLabel *addrlabel = NULL;
addrlabel = new0(AddressLabel, 1);
if (!addrlabel)
return -ENOMEM;
- *ret = addrlabel;
- addrlabel = NULL;
+ *ret = TAKE_PTR(addrlabel);
return 0;
}
@@ -61,8 +42,8 @@ void address_label_free(AddressLabel *label) {
}
static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
- _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
- _cleanup_address_label_free_ AddressLabel *label = NULL;
+ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
+ _cleanup_(address_label_freep) AddressLabel *label = NULL;
int r;
assert(network);
@@ -75,8 +56,7 @@ static int address_label_new_static(Network *network, const char *filename, unsi
label = hashmap_get(network->address_labels_by_section, n);
if (label) {
- *ret = label;
- label = NULL;
+ *ret = TAKE_PTR(label);
return 0;
}
@@ -85,8 +65,7 @@ static int address_label_new_static(Network *network, const char *filename, unsi
if (r < 0)
return r;
- label->section = n;
- n = NULL;
+ label->section = TAKE_PTR(n);
r = hashmap_put(network->address_labels_by_section, label->section, label);
if (r < 0)
@@ -96,8 +75,7 @@ static int address_label_new_static(Network *network, const char *filename, unsi
LIST_APPEND(labels, network->address_labels, label);
network->n_address_labels++;
- *ret = label;
- label = NULL;
+ *ret = TAKE_PTR(label);
return 0;
}
@@ -154,7 +132,7 @@ int config_parse_address_label_prefix(const char *unit,
void *data,
void *userdata) {
- _cleanup_address_label_free_ AddressLabel *n = NULL;
+ _cleanup_(address_label_freep) AddressLabel *n = NULL;
Network *network = userdata;
int r;
@@ -191,7 +169,7 @@ int config_parse_address_label(
void *data,
void *userdata) {
- _cleanup_address_label_free_ AddressLabel *n = NULL;
+ _cleanup_(address_label_freep) AddressLabel *n = NULL;
Network *network = userdata;
uint32_t k;
int r;
@@ -213,7 +191,7 @@ int config_parse_address_label(
}
if (k == 0xffffffffUL) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Adress label is invalid, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring: %s", rvalue);
return 0;
}
diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h
index 9ddf707763..77687edcba 100644
--- a/src/network/networkd-address-label.h
+++ b/src/network/networkd-address-label.h
@@ -1,28 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <inttypes.h>
#include <stdbool.h>
+#include "conf-parser.h"
#include "in-addr-util.h"
typedef struct AddressLabel AddressLabel;
@@ -51,9 +34,8 @@ int address_label_new(AddressLabel **ret);
void address_label_free(AddressLabel *label);
DEFINE_TRIVIAL_CLEANUP_FUNC(AddressLabel*, address_label_free);
-#define _cleanup_address_label_free_ _cleanup_(address_label_freep)
int address_label_configure(AddressLabel *address, Link *link, sd_netlink_message_handler_t callback, bool update);
-int config_parse_address_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_label_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix);
diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c
index 22582ab9f1..2e35f77093 100644
--- a/src/network/networkd-address-pool.c
+++ b/src/network/networkd-address-pool.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "networkd-address-pool.h"
diff --git a/src/network/networkd-address-pool.h b/src/network/networkd-address-pool.h
index 1fcff09be9..bd479a517d 100644
--- a/src/network/networkd-address-pool.h
+++ b/src/network/networkd-address-pool.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct AddressPool AddressPool;
#include "in-addr-util.h"
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 7e722b1a2e..5bddf88e36 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
@@ -37,7 +19,7 @@
#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
int address_new(Address **ret) {
- _cleanup_address_free_ Address *address = NULL;
+ _cleanup_(address_freep) Address *address = NULL;
address = new0(Address, 1);
if (!address)
@@ -48,15 +30,14 @@ int address_new(Address **ret) {
address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME;
address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME;
- *ret = address;
- address = NULL;
+ *ret = TAKE_PTR(address);
return 0;
}
int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
- _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
- _cleanup_address_free_ Address *address = NULL;
+ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
+ _cleanup_(address_freep) Address *address = NULL;
int r;
assert(network);
@@ -70,8 +51,7 @@ int address_new_static(Network *network, const char *filename, unsigned section_
address = hashmap_get(network->addresses_by_section, n);
if (address) {
- *ret = address;
- address = NULL;
+ *ret = TAKE_PTR(address);
return 0;
}
@@ -85,8 +65,7 @@ int address_new_static(Network *network, const char *filename, unsigned section_
return r;
if (filename) {
- address->section = n;
- n = NULL;
+ address->section = TAKE_PTR(n);
r = hashmap_put(network->addresses_by_section, address->section, address);
if (r < 0)
@@ -97,8 +76,7 @@ int address_new_static(Network *network, const char *filename, unsigned section_
LIST_APPEND(addresses, network->static_addresses, address);
network->n_static_addresses++;
- *ret = address;
- address = NULL;
+ *ret = TAKE_PTR(address);
return 0;
}
@@ -258,7 +236,7 @@ static int address_add_internal(Link *link, Set **addresses,
const union in_addr_union *in_addr,
unsigned char prefixlen,
Address **ret) {
- _cleanup_address_free_ Address *address = NULL;
+ _cleanup_(address_freep) Address *address = NULL;
int r;
assert(link);
@@ -488,7 +466,7 @@ int address_remove(
static int address_acquire(Link *link, Address *original, Address **ret) {
union in_addr_union in_addr = {};
struct in_addr broadcast = {};
- _cleanup_address_free_ Address *na = NULL;
+ _cleanup_(address_freep) Address *na = NULL;
int r;
assert(link);
@@ -541,8 +519,7 @@ static int address_acquire(Link *link, Address *original, Address **ret) {
LIST_PREPEND(addresses, link->pool_addresses, na);
- *ret = na;
- na = NULL;
+ *ret = TAKE_PTR(na);
return 0;
}
@@ -685,7 +662,7 @@ int config_parse_broadcast(
void *userdata) {
Network *network = userdata;
- _cleanup_address_free_ Address *n = NULL;
+ _cleanup_(address_freep) Address *n = NULL;
int r;
assert(filename);
@@ -727,7 +704,7 @@ int config_parse_address(const char *unit,
void *userdata) {
Network *network = userdata;
- _cleanup_address_free_ Address *n = NULL;
+ _cleanup_(address_freep) Address *n = NULL;
const char *address, *e;
union in_addr_union buffer;
int r, f;
@@ -813,7 +790,7 @@ int config_parse_label(
void *data,
void *userdata) {
- _cleanup_address_free_ Address *n = NULL;
+ _cleanup_(address_freep) Address *n = NULL;
Network *network = userdata;
int r;
@@ -852,7 +829,7 @@ int config_parse_lifetime(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
- _cleanup_address_free_ Address *n = NULL;
+ _cleanup_(address_freep) Address *n = NULL;
unsigned k;
int r;
@@ -900,7 +877,7 @@ int config_parse_address_flags(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
- _cleanup_address_free_ Address *n = NULL;
+ _cleanup_(address_freep) Address *n = NULL;
int r;
assert(filename);
@@ -944,7 +921,7 @@ int config_parse_address_scope(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
- _cleanup_address_free_ Address *n = NULL;
+ _cleanup_(address_freep) Address *n = NULL;
int r;
assert(filename);
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index c2a241b571..63e8f5d1ec 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -1,28 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <inttypes.h>
#include <stdbool.h>
+#include "conf-parser.h"
#include "in-addr-util.h"
typedef struct Address Address;
@@ -78,11 +61,10 @@ bool address_equal(Address *a1, Address *a2);
bool address_is_ready(const Address *a);
DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
-#define _cleanup_address_free_ _cleanup_(address_freep)
-
-int config_parse_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_broadcast(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_lifetime(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_scope(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_address);
+CONFIG_PARSER_PROTOTYPE(config_parse_broadcast);
+CONFIG_PARSER_PROTOTYPE(config_parse_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_lifetime);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_flags);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_scope);
diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c
index 99dd416296..8e8a618e21 100644
--- a/src/network/networkd-brvlan.c
+++ b/src/network/networkd-brvlan.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2016 BISDN GmbH. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 BISDN GmbH. All rights reserved.
***/
#include <netinet/in.h>
diff --git a/src/network/networkd-brvlan.h b/src/network/networkd-brvlan.h
index be99436b67..f6af140d3e 100644
--- a/src/network/networkd-brvlan.h
+++ b/src/network/networkd-brvlan.h
@@ -2,30 +2,17 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2016 BISDN GmbH. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 BISDN GmbH. All rights reserved.
***/
#include <stdint.h>
+#include "conf-parser.h"
+
typedef struct Link Link;
int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap);
-int config_parse_brvlan_pvid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_brvlan_vlan(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_brvlan_untagged(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_pvid);
+CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_vlan);
+CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_untagged);
diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c
index 1f791fcec0..05bbc0b3e9 100644
--- a/src/network/networkd-conf.c
+++ b/src/network/networkd-conf.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.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/>.
+ Copyright © 2014 Vinay Kulkarni <kulkarniv@vmware.com>
***/
#include <ctype.h>
diff --git a/src/network/networkd-conf.h b/src/network/networkd-conf.h
index 8d93cff61c..88a2c64031 100644
--- a/src/network/networkd-conf.h
+++ b/src/network/networkd-conf.h
@@ -2,49 +2,16 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.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/>.
+ Copyright © 2014 Vinay Kulkarni <kulkarniv@vmware.com>
***/
+#include "conf-parser.h"
+
typedef struct Manager Manager;
int manager_parse_config_file(Manager *m);
const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-int config_parse_duid_type(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
-int config_parse_duid_rawdata(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_duid_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_duid_rawdata);
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index aaea2ae908..34c1f63568 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/ether.h>
#include <linux/if.h>
@@ -35,7 +17,7 @@
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link);
@@ -111,7 +93,7 @@ static int link_set_dhcp_routes(Link *link) {
}
for (i = 0; i < n; i++) {
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
/* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
the DHCP client MUST ignore the Static Routes option. */
@@ -150,8 +132,8 @@ static int link_set_dhcp_routes(Link *link) {
log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option");
if (r >= 0 && !classless_route) {
- _cleanup_route_free_ Route *route = NULL;
- _cleanup_route_free_ Route *route_gw = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_freep) Route *route_gw = NULL;
r = route_new(&route);
if (r < 0)
@@ -201,7 +183,7 @@ static int link_set_dhcp_routes(Link *link) {
}
static int dhcp_lease_lost(Link *link) {
- _cleanup_address_free_ Address *address = NULL;
+ _cleanup_(address_freep) Address *address = NULL;
struct in_addr addr;
struct in_addr netmask;
struct in_addr gateway;
@@ -220,7 +202,7 @@ static int dhcp_lease_lost(Link *link) {
n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
if (n >= 0) {
for (i = 0; i < n; i++) {
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
r = route_new(&route);
if (r >= 0) {
@@ -240,8 +222,8 @@ static int dhcp_lease_lost(Link *link) {
if (r >= 0) {
r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
if (r >= 0) {
- _cleanup_route_free_ Route *route_gw = NULL;
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(route_freep) Route *route_gw = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
r = route_new(&route_gw);
if (r >= 0) {
@@ -318,7 +300,7 @@ static int dhcp_lease_lost(Link *link) {
static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link);
@@ -344,7 +326,7 @@ static int dhcp4_update_address(Link *link,
struct in_addr *address,
struct in_addr *netmask,
uint32_t lifetime) {
- _cleanup_address_free_ Address *addr = NULL;
+ _cleanup_(address_freep) Address *addr = NULL;
unsigned prefixlen;
int r;
@@ -457,8 +439,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
ADDRESS_FMT_VAL(gateway)),
"ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen,
- "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway),
- NULL);
+ "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway));
else
log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link),
@@ -466,8 +447,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
ADDRESS_FMT_VAL(address),
prefixlen),
"ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
- "PREFIXLEN=%u", prefixlen,
- NULL);
+ "PREFIXLEN=%u", prefixlen);
link->dhcp_lease = sd_dhcp_lease_ref(lease);
link_dirty(link);
@@ -761,6 +741,12 @@ int dhcp4_configure(Link *link) {
return r;
}
+ if (link->network->dhcp_user_class) {
+ r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
+ if (r < 0)
+ return r;
+ }
+
if (link->network->dhcp_client_port) {
r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
if (r < 0)
@@ -781,6 +767,18 @@ int dhcp4_configure(Link *link) {
return r;
break;
}
+ case DHCP_CLIENT_ID_DUID_ONLY: {
+ /* If configured, apply user specified DUID */
+ const DUID *duid = link_duid(link);
+
+ r = sd_dhcp_client_set_duid(link->dhcp_client,
+ duid->type,
+ duid->raw_data_len > 0 ? duid->raw_data : NULL,
+ duid->raw_data_len);
+ if (r < 0)
+ return r;
+ break;
+ }
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
ARPHRD_ETHER,
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index f82e915399..0fcd2cab3e 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <netinet/ether.h>
@@ -267,7 +252,7 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link);
@@ -299,7 +284,7 @@ static int dhcp6_address_change(
uint32_t lifetime_preferred,
uint32_t lifetime_valid) {
- _cleanup_address_free_ Address *addr = NULL;
+ _cleanup_(address_freep) Address *addr = NULL;
char buffer[INET6_ADDRSTRLEN];
int r;
@@ -419,7 +404,7 @@ int dhcp6_request_address(Link *link, int ir) {
if (r < 0)
return r;
else
- running = !!r;
+ running = r;
if (running) {
r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c
index 380581e09a..11f70723a9 100644
--- a/src/network/networkd-fdb.c
+++ b/src/network/networkd-fdb.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <net/ethernet.h>
@@ -38,7 +23,7 @@ int fdb_entry_new_static(
unsigned section,
FdbEntry **ret) {
- _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
+ _cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
struct ether_addr *mac_addr = NULL;
assert(network);
@@ -48,8 +33,7 @@ int fdb_entry_new_static(
if (section) {
fdb_entry = hashmap_get(network->fdb_entries_by_section, UINT_TO_PTR(section));
if (fdb_entry) {
- *ret = fdb_entry;
- fdb_entry = NULL;
+ *ret = TAKE_PTR(fdb_entry);
return 0;
}
@@ -85,8 +69,7 @@ int fdb_entry_new_static(
}
/* return allocated FDB structure. */
- *ret = fdb_entry;
- fdb_entry = NULL;
+ *ret = TAKE_PTR(fdb_entry);
return 0;
}
@@ -192,7 +175,7 @@ int config_parse_fdb_hwaddr(
void *userdata) {
Network *network = userdata;
- _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
+ _cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
int r;
assert(filename);
@@ -238,7 +221,7 @@ int config_parse_fdb_vlan_id(
void *userdata) {
Network *network = userdata;
- _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
+ _cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
int r;
assert(filename);
diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h
index d34d3e5cbd..ac0d131a99 100644
--- a/src/network/networkd-fdb.h
+++ b/src/network/networkd-fdb.h
@@ -2,24 +2,10 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
+#include "conf-parser.h"
#include "list.h"
#include "macro.h"
@@ -42,7 +28,6 @@ void fdb_entry_free(FdbEntry *fdb_entry);
int fdb_entry_configure(Link *link, FdbEntry *fdb_entry);
DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free);
-#define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep)
-int config_parse_fdb_hwaddr(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_fdb_vlan_id(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);
diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c
index e3ebbddfee..a710240f94 100644
--- a/src/network/networkd-ipv4ll.c
+++ b/src/network/networkd-ipv4ll.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/ether.h>
#include <linux/if.h>
@@ -27,8 +9,8 @@
#include "networkd-link.h"
static int ipv4ll_address_lost(Link *link) {
- _cleanup_address_free_ Address *address = NULL;
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(address_freep) Address *address = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
struct in_addr addr;
int r;
@@ -74,7 +56,7 @@ static int ipv4ll_address_lost(Link *link) {
}
static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link);
@@ -95,7 +77,7 @@ static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *u
}
static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link);
@@ -117,8 +99,8 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void
}
static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
- _cleanup_address_free_ Address *ll_addr = NULL;
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(address_freep) Address *ll_addr = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
struct in_addr address;
int r;
diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c
index 1a357ac8e6..3ebbacabaa 100644
--- a/src/network/networkd-ipv6-proxy-ndp.c
+++ b/src/network/networkd-ipv6-proxy-ndp.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2017 Florian Klink <flokli@flokli.de>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2017 Florian Klink <flokli@flokli.de>
***/
#include <netinet/ether.h>
diff --git a/src/network/networkd-ipv6-proxy-ndp.h b/src/network/networkd-ipv6-proxy-ndp.h
index ac24c58637..d06273be39 100644
--- a/src/network/networkd-ipv6-proxy-ndp.h
+++ b/src/network/networkd-ipv6-proxy-ndp.h
@@ -2,24 +2,10 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2017 Florian Klink <flokli@flokli.de>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2017 Florian Klink <flokli@flokli.de>
***/
+#include "conf-parser.h"
#include "list.h"
#include "macro.h"
@@ -34,7 +20,6 @@ struct IPv6ProxyNDPAddress {
LIST_FIELDS(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
};
-
int ipv6_proxy_ndp_address_new_static(Network *network, IPv6ProxyNDPAddress ** ipv6_proxy_ndp_address);
void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address);
int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy_ndp_address);
@@ -42,4 +27,4 @@ int ipv6_proxy_ndp_addresses_configure(Link *link);
DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6ProxyNDPAddress*, ipv6_proxy_ndp_address_free);
-int config_parse_ipv6_proxy_ndp_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address);
diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c
index 2f4850b1a1..0dbcd86d9e 100644
--- a/src/network/networkd-link-bus.c
+++ b/src/network/networkd-link-bus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-util.h"
@@ -82,8 +64,7 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
}
l[c] = NULL;
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 31d3f7ade7..4afcf843bd 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1,25 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/ether.h>
#include <linux/if.h>
+#include <linux/can/netlink.h>
#include <unistd.h>
#include <stdio_ext.h>
@@ -417,7 +400,7 @@ static int link_update_flags(Link *link, sd_netlink_message *m) {
}
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
- _cleanup_link_unref_ Link *link = NULL;
+ _cleanup_(link_unrefp) Link *link = NULL;
uint16_t type;
const char *ifname, *kind = NULL;
int r, ifindex;
@@ -501,8 +484,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
if (r < 0)
return r;
- *ret = link;
- link = NULL;
+ *ret = TAKE_PTR(link);
return 0;
}
@@ -821,7 +803,7 @@ static int link_set_routing_policy_rule(Link *link) {
}
static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link->route_messages > 0);
@@ -880,7 +862,7 @@ static int link_enter_set_routes(Link *link) {
}
int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(m);
@@ -898,7 +880,7 @@ int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *use
}
static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(rtnl);
@@ -929,7 +911,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
}
static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(rtnl);
@@ -1164,7 +1146,6 @@ static int link_enter_set_addresses(Link *link) {
log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
}
-
if (link->network->dhcp_server_emit_ntp) {
if (link->network->n_dhcp_server_ntp > 0)
@@ -1232,7 +1213,7 @@ static int link_enter_set_addresses(Link *link) {
}
int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(m);
@@ -1276,7 +1257,7 @@ static int link_set_proxy_arp(Link *link) {
}
static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
log_link_debug(link, "Set link");
@@ -1292,7 +1273,7 @@ static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userd
}
static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(m);
@@ -1323,6 +1304,24 @@ int link_set_mtu(Link *link, uint32_t mtu) {
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+ /* If IPv6 not configured (no static IPv6 address and IPv6LL autoconfiguration is disabled)
+ for this interface, or if it is a bridge slave, then disable IPv6 else enable it. */
+ (void) link_enable_ipv6(link);
+
+ /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes
+ on the interface. Bump up MTU bytes to IPV6_MTU_MIN. */
+ if (link_ipv6_enabled(link) && link->network->mtu < IPV6_MIN_MTU) {
+
+ log_link_warning(link, "Bumping MTU to " STRINGIFY(IPV6_MIN_MTU) ", as "
+ "IPv6 is requested and requires a minimum MTU of " STRINGIFY(IPV6_MIN_MTU) " bytes: %m");
+
+ link->network->mtu = IPV6_MIN_MTU;
+ }
+
+ r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set MTU: %m");
+
r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu);
if (r < 0)
return log_link_error_errno(link, r, "Could not append MTU: %m");
@@ -1339,7 +1338,7 @@ int link_set_mtu(Link *link, uint32_t mtu) {
}
static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(m);
@@ -1372,7 +1371,7 @@ static int link_set_flags(Link *link) {
if (!link->network)
return 0;
- if (link->network->arp < 0)
+ if (link->network->arp < 0 && link->network->multicast < 0 && link->network->allmulticast < 0)
return 0;
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
@@ -1381,7 +1380,17 @@ static int link_set_flags(Link *link) {
if (link->network->arp >= 0) {
ifi_change |= IFF_NOARP;
- ifi_flags |= link->network->arp ? 0 : IFF_NOARP;
+ SET_FLAG(ifi_flags, IFF_NOARP, link->network->arp == 0);
+ }
+
+ if (link->network->multicast >= 0) {
+ ifi_change |= IFF_MULTICAST;
+ SET_FLAG(ifi_flags, IFF_MULTICAST, link->network->multicast);
+ }
+
+ if (link->network->allmulticast >= 0) {
+ ifi_change |= IFF_ALLMULTI;
+ SET_FLAG(ifi_flags, IFF_ALLMULTI, link->network->allmulticast);
}
r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change);
@@ -1416,25 +1425,37 @@ static int link_set_bridge(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
- r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
+ if (link->network->use_bpdu >= 0) {
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, link->network->use_bpdu);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
+ }
- r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
+ if (link->network->hairpin >= 0) {
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
+ }
- r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
+ if (link->network->fast_leave >= 0) {
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
+ }
- r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
+ if (link->network->allow_port_to_be_root >= 0) {
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
- r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
+ }
+
+ if (link->network->unicast_flood >= 0) {
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
+
+ }
if (link->network->cost != 0) {
r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
@@ -1718,7 +1739,7 @@ bool link_has_carrier(Link *link) {
}
static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link);
@@ -1768,26 +1789,6 @@ int link_up(Link *link) {
return log_link_error_errno(link, r, "Could not set MAC address: %m");
}
- /* If IPv6 not configured (no static IPv6 address and IPv6LL autoconfiguration is disabled)
- for this interface, or if it is a bridge slave, then disable IPv6 else enable it. */
- (void) link_enable_ipv6(link);
-
- if (link->network->mtu) {
- /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes
- on the interface. Bump up MTU bytes to IPV6_MTU_MIN. */
- if (link_ipv6_enabled(link) && link->network->mtu < IPV6_MIN_MTU) {
-
- log_link_warning(link, "Bumping MTU to " STRINGIFY(IPV6_MIN_MTU) ", as "
- "IPv6 is requested and requires a minimum MTU of " STRINGIFY(IPV6_MIN_MTU) " bytes: %m");
-
- link->network->mtu = IPV6_MIN_MTU;
- }
-
- r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set MTU: %m");
- }
-
r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
if (r < 0)
return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
@@ -1840,67 +1841,171 @@ int link_up(Link *link) {
return 0;
}
-static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+static int link_up_can(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
+ log_link_debug(link, "Bringing CAN link up");
- r = sd_netlink_message_get_errno(m);
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0)
- log_link_warning_errno(link, r, "Could not bring down interface: %m");
+ return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
- return 1;
+ r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set link flags: %m");
+
+ r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+
+ return 0;
}
-int link_down(Link *link) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+static int link_set_can(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(link);
+ assert(link->network);
assert(link->manager);
assert(link->manager->rtnl);
- log_link_debug(link, "Bringing link down");
+ log_link_debug(link, "link_set_can");
- r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
- RTM_SETLINK, link->ifindex);
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
if (r < 0)
- return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+ return log_link_error_errno(link, r, "Failed to allocate netlink message: %m");
- r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
+ r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK);
if (r < 0)
- return log_link_error_errno(link, r, "Could not set link flags: %m");
+ return log_link_error_errno(link, r, "Could not set netlink flags: %m");
- r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL);
+ r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to open netlink container: %m");
+
+ r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+ if (link->network->can_bitrate > 0 || link->network->can_sample_point > 0) {
+ struct can_bittiming bt = {
+ .bitrate = link->network->can_bitrate,
+ .sample_point = link->network->can_sample_point,
+ };
+
+ if (link->network->can_bitrate > UINT32_MAX) {
+ log_link_error(link, "bitrate (%zu) too big.", link->network->can_bitrate);
+ return -ERANGE;
+ }
+
+ log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate);
+ if (link->network->can_sample_point > 0)
+ log_link_debug(link, "Setting sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10);
+ else
+ log_link_debug(link, "Using default sample point");
+
+ r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
+ }
+
+ if (link->network->can_restart_us > 0) {
+ char time_string[FORMAT_TIMESPAN_MAX];
+ uint64_t restart_ms;
+
+ if (link->network->can_restart_us == USEC_INFINITY)
+ restart_ms = 0;
+ else
+ restart_ms = DIV_ROUND_UP(link->network->can_restart_us, USEC_PER_MSEC);
+
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, restart_ms * 1000, MSEC_PER_SEC);
+
+ if (restart_ms > UINT32_MAX) {
+ log_link_error(link, "restart timeout (%s) too big.", time_string);
+ return -ERANGE;
+ }
+
+ log_link_debug(link, "Setting restart = %s", time_string);
+
+ r = sd_netlink_message_append_u32(m, IFLA_CAN_RESTART_MS, restart_ms);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
+ }
+
+ r = sd_netlink_message_close_container(m);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to close netlink container: %m");
+
+ r = sd_netlink_message_close_container(m);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to close netlink container: %m");
+
+ r = sd_netlink_call_async(link->manager->rtnl, m, link_set_handler, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
- return 0;
+ if (!(link->flags & IFF_UP)) {
+ r = link_up_can(link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return r;
+ }
+ }
+
+ log_link_debug(link, "link_set_can done");
+
+ return r;
}
-static int link_up_can(Link *link) {
+static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+ _cleanup_(link_unrefp) Link *link = userdata;
+ int r;
+
+ assert(link);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Could not bring down interface: %m");
+
+ if (streq_ptr(link->kind, "can")) {
+ link_ref(link);
+ link_set_can(link);
+ }
+
+ return 1;
+}
+
+int link_down(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
+ assert(link->manager);
+ assert(link->manager->rtnl);
- log_link_debug(link, "Bringing CAN link up");
+ log_link_debug(link, "Bringing link down");
- r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
+ RTM_SETLINK, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
- r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
+ r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
if (r < 0)
return log_link_error_errno(link, r, "Could not set link flags: %m");
- r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
+ r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@@ -2205,7 +2310,7 @@ static int link_joined(Link *link) {
}
static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link);
@@ -2253,17 +2358,14 @@ static int link_enter_join_netdev(Link *link) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(link->network->bond),
- LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname),
- NULL);
+ LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname));
r = netdev_join(link->network->bond, link, netdev_join_handler);
if (r < 0) {
log_struct_errno(LOG_WARNING, r,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(link->network->bond),
- LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname),
- NULL);
-
+ LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname));
link_enter_failed(link);
return r;
}
@@ -2275,16 +2377,14 @@ static int link_enter_join_netdev(Link *link) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(link->network->bridge),
- LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname),
- NULL);
+ LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname));
r = netdev_join(link->network->bridge, link, netdev_join_handler);
if (r < 0) {
log_struct_errno(LOG_WARNING, r,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(link->network->bridge),
- LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname),
- NULL),
+ LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname));
link_enter_failed(link);
return r;
}
@@ -2296,15 +2396,14 @@ static int link_enter_join_netdev(Link *link) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(link->network->vrf),
- LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->vrf->ifname),
- NULL);
+ LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->vrf->ifname));
+
r = netdev_join(link->network->vrf, link, netdev_join_handler);
if (r < 0) {
log_struct_errno(LOG_WARNING, r,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(link->network->vrf),
- LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->vrf->ifname),
- NULL);
+ LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->vrf->ifname));
link_enter_failed(link);
return r;
}
@@ -2322,16 +2421,14 @@ static int link_enter_join_netdev(Link *link) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(netdev),
- LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname),
- NULL);
+ LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname));
r = netdev_join(netdev, link, netdev_join_handler);
if (r < 0) {
log_struct_errno(LOG_WARNING, r,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(netdev),
- LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname),
- NULL);
+ LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname));
link_enter_failed(link);
return r;
}
@@ -2484,6 +2581,32 @@ static int link_set_ipv6_hop_limit(Link *link) {
return 0;
}
+static int link_set_ipv6_mtu(Link *link) {
+ char buf[DECIMAL_STR_MAX(unsigned) + 1];
+ const char *p = NULL;
+ int r;
+
+ /* Make this a NOP if IPv6 is not available */
+ if (!socket_ipv6_is_supported())
+ return 0;
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (link->network->ipv6_mtu == 0)
+ return 0;
+
+ p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/mtu");
+
+ xsprintf(buf, "%" PRIu32, link->network->ipv6_mtu);
+
+ r = write_string_file(p, buf, 0);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m");
+
+ return 0;
+}
+
static int link_drop_foreign_config(Link *link) {
Address *address;
Route *route;
@@ -2574,26 +2697,45 @@ static int link_update_lldp(Link *link) {
return r;
}
-static int link_configure(Link *link) {
+static int link_configure_can(Link *link) {
int r;
- assert(link);
- assert(link->network);
- assert(link->state == LINK_STATE_PENDING);
-
- if (streq_ptr(link->kind, "vcan")) {
-
- if (!(link->flags & IFF_UP)) {
- r = link_up_can(link);
+ if (streq_ptr(link->kind, "can")) {
+ /* The CAN interface must be down to configure bitrate, etc... */
+ if ((link->flags & IFF_UP)) {
+ r = link_down(link);
if (r < 0) {
link_enter_failed(link);
return r;
}
+
+ return 0;
}
- return 0;
+ return link_set_can(link);
+ }
+
+ if (!(link->flags & IFF_UP)) {
+ r = link_up_can(link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return r;
+ }
}
+ return 0;
+}
+
+static int link_configure(Link *link) {
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->state == LINK_STATE_PENDING);
+
+ if (STRPTR_IN_SET(link->kind, "can", "vcan"))
+ return link_configure_can(link);
+
/* Drop foreign config, but ignore loopback or critical devices.
* We do not want to remove loopback address or addresses used for root NFS. */
if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) {
@@ -2638,6 +2780,10 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
+ r = link_set_ipv6_mtu(link);
+ if (r < 0)
+ return r;
+
if (link_ipv4ll_enabled(link)) {
r = ipv4ll_configure(link);
if (r < 0)
@@ -2716,6 +2862,12 @@ static int link_configure(Link *link) {
return r;
}
+ if (link->network->mtu > 0) {
+ r = link_set_mtu(link, link->network->mtu);
+ if (r < 0)
+ return r;
+ }
+
if (link_has_carrier(link) || link->network->configure_without_carrier) {
r = link_acquire_conf(link);
if (r < 0)
@@ -2727,7 +2879,7 @@ static int link_configure(Link *link) {
static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
Network *network;
int r;
@@ -2839,7 +2991,7 @@ static int link_load(Link *link) {
assert(link);
- r = parse_env_file(link->state_file, NEWLINE,
+ r = parse_env_file(NULL, link->state_file, NEWLINE,
"NETWORK_FILE", &network_file,
"ADDRESSES", &addresses,
"ROUTES", &routes,
@@ -2964,7 +3116,7 @@ network_file_fail:
if (r < 0)
return log_link_error_errno(link, r, "Failed to add route: %m");
- if (lifetime != USEC_INFINITY) {
+ if (lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) {
r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime,
0, route_expire_handler, route);
if (r < 0)
@@ -2973,8 +3125,7 @@ network_file_fail:
route->lifetime = lifetime;
sd_event_source_unref(route->expire);
- route->expire = expire;
- expire = NULL;
+ route->expire = TAKE_PTR(expire);
}
}
@@ -3019,7 +3170,7 @@ ipv4ll_address_fail:
int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
Link *link;
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
int r;
@@ -3201,21 +3352,24 @@ int link_update(Link *link, sd_netlink_message *m) {
if (r >= 0 && !streq(ifname, link->ifname)) {
log_link_info(link, "Interface name change detected, %s has been renamed to %s.", link->ifname, ifname);
- link_free_carrier_maps(link);
-
- r = free_and_strdup(&link->ifname, ifname);
- if (r < 0)
- return r;
+ if (link->state == LINK_STATE_PENDING) {
+ r = free_and_strdup(&link->ifname, ifname);
+ if (r < 0)
+ return r;
+ } else {
+ Manager *manager = link->manager;
- r = link_new_carrier_maps(link);
- if (r < 0)
- return r;
+ link_drop(link);
+ r = link_add(manager, m, &link);
+ if (r < 0)
+ return r;
+ }
}
r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
if (r >= 0 && mtu > 0) {
link->mtu = mtu;
- if (!link->original_mtu) {
+ if (link->original_mtu == 0) {
link->original_mtu = mtu;
log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
}
@@ -3282,6 +3436,17 @@ int link_update(Link *link, sd_netlink_message *m) {
return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m");
break;
}
+ case DHCP_CLIENT_ID_DUID_ONLY: {
+ const DUID *duid = link_duid(link);
+
+ r = sd_dhcp_client_set_duid(link->dhcp_client,
+ duid->type,
+ duid->raw_data_len > 0 ? duid->raw_data : NULL,
+ duid->raw_data_len);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DUID in DHCP client: %m");
+ break;
+ }
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
ARPHRD_ETHER,
@@ -3491,7 +3656,7 @@ int link_save(Link *link) {
/* Make sure to flush out old entries before we use the NDISC data */
ndisc_vacuum(link);
- if (link->network->dhcp_use_dns && link->ndisc_rdnss) {
+ if (link->network->ipv6_accept_ra_use_dns && link->ndisc_rdnss) {
NDiscRDNSS *dd;
SET_FOREACH(dd, link->ndisc_rdnss, i) {
@@ -3596,6 +3761,10 @@ int link_save(Link *link) {
fprintf(f, "MDNS=%s\n",
resolve_support_to_string(link->network->mdns));
+ if (link->network->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
+ fprintf(f, "DNS_OVER_TLS=%s\n",
+ dns_over_tls_mode_to_string(link->network->dns_over_tls_mode));
+
if (link->network->dnssec_mode != _DNSSEC_MODE_INVALID)
fprintf(f, "DNSSEC=%s\n",
dnssec_mode_to_string(link->network->dnssec_mode));
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 8aaaa679ff..7e22dfd504 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <endian.h>
@@ -101,7 +83,7 @@ typedef struct Link {
sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease;
char *lease_file;
- uint16_t original_mtu;
+ uint32_t original_mtu;
unsigned dhcp4_messages;
bool dhcp4_configured;
bool dhcp6_configured;
@@ -192,7 +174,6 @@ int link_object_find(sd_bus *bus, const char *path, const char *interface, void
int link_send_changed(Link *link, const char *property, ...) _sentinel_;
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
-#define _cleanup_link_unref_ _cleanup_(link_unrefp)
/* Macros which append INTERFACE= to the message */
diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c
index b8d160a1f8..51fadc8125 100644
--- a/src/network/networkd-lldp-tx.c
+++ b/src/network/networkd-lldp-tx.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <endian.h>
#include <inttypes.h>
@@ -198,10 +180,9 @@ static int lldp_make_packet(
assert(p == (uint8_t*) packet + l);
- *ret = packet;
+ *ret = TAKE_PTR(packet);
*sz = l;
- packet = NULL;
return 0;
}
@@ -263,7 +244,7 @@ static int link_send_lldp(Link *link) {
return r;
(void) gethostname_strict(&hostname);
- (void) parse_env_file("/etc/machine-info", NEWLINE, "PRETTY_HOSTNAME", &pretty_hostname, NULL);
+ (void) parse_env_file(NULL, "/etc/machine-info", NEWLINE, "PRETTY_HOSTNAME", &pretty_hostname, NULL);
assert_cc(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1 <= (UINT16_MAX - 1) * USEC_PER_SEC);
ttl = DIV_ROUND_UP(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1, USEC_PER_SEC);
diff --git a/src/network/networkd-lldp-tx.h b/src/network/networkd-lldp-tx.h
index be7a989226..860065cc6d 100644
--- a/src/network/networkd-lldp-tx.h
+++ b/src/network/networkd-lldp-tx.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "networkd-link.h"
typedef enum LLDPEmit {
diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c
index 6d57036eb5..6e2c79bce1 100644
--- a/src/network/networkd-manager-bus.c
+++ b/src/network/networkd-manager-bus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-util.h"
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 1c519d8c49..1c4866077b 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
#include <sys/socket.h>
#include <linux/if.h>
@@ -144,7 +126,7 @@ int manager_connect_bus(Manager *m) {
if (m->bus)
return 0;
- r = bus_open_system_watch_bind(&m->bus);
+ r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-network");
if (r < 0)
return log_error_errno(r, "Failed to connect to bus: %m");
@@ -168,7 +150,7 @@ int manager_connect_bus(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to add network enumerator: %m");
- r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.network1", 0, NULL, NULL);
+ r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.network1", 0, NULL);
if (r < 0)
return log_error_errno(r, "Failed to request name: %m");
@@ -233,7 +215,7 @@ static int manager_udev_process_link(Manager *m, struct udev_device *device) {
static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
struct udev_monitor *monitor = m->udev_monitor;
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
device = udev_monitor_receive_device(monitor);
if (!device)
@@ -781,7 +763,7 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
} else if (r >= 0) {
r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &from_prefixlen);
if (r < 0) {
- log_warning_errno(r, "rtnl: failed to retrive rule from prefix length, ignoring: %m");
+ log_warning_errno(r, "rtnl: failed to retrieve rule from prefix length, ignoring: %m");
return 0;
}
}
@@ -793,7 +775,7 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
} else if (r >= 0) {
r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &to_prefixlen);
if (r < 0) {
- log_warning_errno(r, "rtnl: failed to retrive rule to prefix length, ignoring: %m");
+ log_warning_errno(r, "rtnl: failed to retrieve rule to prefix length, ignoring: %m");
return 0;
}
}
@@ -808,7 +790,7 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
} else if (r >= 0) {
r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &from_prefixlen);
if (r < 0) {
- log_warning_errno(r, "rtnl: failed to retrive rule from prefix length, ignoring: %m");
+ log_warning_errno(r, "rtnl: failed to retrieve rule from prefix length, ignoring: %m");
return 0;
}
}
@@ -820,7 +802,7 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi
} else if (r >= 0) {
r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &to_prefixlen);
if (r < 0) {
- log_warning_errno(r, "rtnl: failed to retrive rule to prefix length, ignoring: %m");
+ log_warning_errno(r, "rtnl: failed to retrieve rule to prefix length, ignoring: %m");
return 0;
}
}
@@ -1389,7 +1371,7 @@ static const struct hash_ops dhcp6_prefixes_hash_ops = {
};
int manager_new(Manager **ret, sd_event *event) {
- _cleanup_manager_free_ Manager *m = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
int r;
m = new0(Manager, 1);
@@ -1444,8 +1426,7 @@ int manager_new(Manager **ret, sd_event *event) {
(void) routing_policy_load_rules(m->state_file, &m->rules_saved);
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
@@ -1498,7 +1479,6 @@ void manager_free(Manager *m) {
sd_bus_unref(m->bus);
sd_bus_slot_unref(m->prepare_for_sleep_slot);
sd_bus_slot_unref(m->connected_slot);
- sd_event_source_unref(m->bus_retry_event_source);
free(m->dynamic_timezone);
free(m->dynamic_hostname);
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index 229812ae0e..fbb7f5413a 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
@@ -44,7 +26,6 @@ struct Manager {
sd_netlink *genl;
sd_event *event;
sd_resolve *resolve;
- sd_event_source *bus_retry_event_source;
sd_bus *bus;
sd_bus_slot *prepare_for_sleep_slot;
sd_bus_slot *connected_slot;
@@ -121,4 +102,3 @@ int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr);
int manager_dhcp6_prefix_remove_all(Manager *m, Link *link);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
-#define _cleanup_manager_free_ _cleanup_(manager_freep)
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index df4630bf12..8284e3a299 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <netinet/icmp6.h>
@@ -31,7 +16,7 @@
#define NDISC_PREFIX_LFT_MIN 7200U
static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(link);
@@ -52,7 +37,7 @@ static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *
}
static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
struct in6_addr gateway;
uint16_t lifetime;
unsigned preference;
@@ -151,7 +136,7 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
}
static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
- _cleanup_address_free_ Address *address = NULL;
+ _cleanup_(address_freep) Address *address = NULL;
Address *existing_address;
uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
usec_t time_now;
@@ -249,7 +234,7 @@ static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *
}
static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
usec_t time_now;
uint32_t lifetime;
unsigned prefixlen;
@@ -307,7 +292,7 @@ static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt)
}
static void ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
struct in6_addr gateway;
uint32_t lifetime;
unsigned preference, prefixlen;
diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h
index f5eb8cd360..351fc695c6 100644
--- a/src/network/networkd-ndisc.h
+++ b/src/network/networkd-ndisc.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "networkd-link.h"
diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c
index 8d3d7236fc..07e453cc80 100644
--- a/src/network/networkd-network-bus.c
+++ b/src/network/networkd-network-bus.c
@@ -1,24 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
+#include "ether-addr-util.h"
#include "networkd-manager.h"
#include "string-util.h"
#include "strv.h"
@@ -32,23 +15,24 @@ static int property_get_ether_addrs(
void *userdata,
sd_bus_error *error) {
- Network *n = userdata;
- const char *ether = NULL;
+ char buf[ETHER_ADDR_TO_STRING_MAX];
+ const struct ether_addr *p;
+ Iterator i;
+ Set *s;
int r;
assert(bus);
assert(reply);
- assert(n);
+ assert(userdata);
- if (n->match_mac)
- ether = ether_ntoa(n->match_mac);
+ s = *(Set **) userdata;
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
- if (ether) {
- r = sd_bus_message_append(reply, "s", strempty(ether));
+ SET_FOREACH(p, s, i) {
+ r = sd_bus_message_append(reply, "s", ether_addr_to_string(p, buf));
if (r < 0)
return r;
}
@@ -61,7 +45,7 @@ const sd_bus_vtable network_vtable[] = {
SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, offsetof(Network, match_mac), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -122,8 +106,7 @@ int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
return r;
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 281ba657b3..6ad5257f79 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -4,9 +4,9 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#endif
#include <stddef.h>
#include "conf-parser.h"
+#include "network-internal.h"
#include "networkd-conf.h"
#include "networkd-network.h"
-#include "network-internal.h"
#include "vlan-util.h"
%}
struct ConfigPerfItem;
@@ -20,7 +20,7 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac)
+Match.MACAddress, config_parse_hwaddrs, 0, offsetof(Network, match_mac)
Match.Path, config_parse_strv, 0, offsetof(Network, match_path)
Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver)
Match.Type, config_parse_strv, 0, offsetof(Network, match_type)
@@ -31,8 +31,10 @@ Match.KernelCommandLine, config_parse_net_condition,
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(Network, match_kernel_version)
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
-Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
+Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(Network, mtu)
Link.ARP, config_parse_tristate, 0, offsetof(Network, arp)
+Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast)
+Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast)
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
Link.RequiredForOnline, config_parse_bool, 0, offsetof(Network, required_for_online)
Network.Description, config_parse_string, 0, offsetof(Network, description)
@@ -58,6 +60,7 @@ Network.Domains, config_parse_domains,
Network.DNS, config_parse_dns, 0, 0
Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr)
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
+Network.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Network, dns_over_tls_mode)
Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode)
Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0
Network.NTP, config_parse_ntp, 0, offsetof(Network, ntp)
@@ -69,6 +72,7 @@ Network.IPv6AcceptRouterAdvertisements, config_parse_tristate,
Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits)
Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit)
Network.IPv6ProxyNDP, config_parse_tristate, 0, offsetof(Network, ipv6_proxy_ndp)
+Network.IPv6MTUBytes, config_parse_mtu, AF_INET6, 0
Network.ActiveSlave, config_parse_bool, 0, offsetof(Network, active_slave)
Network.PrimarySlave, config_parse_bool, 0, offsetof(Network, primary_slave)
Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
@@ -104,6 +108,7 @@ Route.Metric, config_parse_route_priority,
Route.Scope, config_parse_route_scope, 0, 0
Route.PreferredSource, config_parse_preferred_src, 0, 0
Route.Table, config_parse_route_table, 0, 0
+Route.MTUBytes, config_parse_route_mtu, AF_UNSPEC, 0
Route.GatewayOnlink, config_parse_gateway_onlink, 0, 0
Route.IPv6Preference, config_parse_ipv6_route_preference, 0, 0
Route.Protocol, config_parse_route_protocol, 0, 0
@@ -124,6 +129,7 @@ DHCP.Hostname, config_parse_hostname,
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
+DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
@@ -147,11 +153,11 @@ DHCPServer.Timezone, config_parse_timezone,
DHCPServer.PoolOffset, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_offset)
DHCPServer.PoolSize, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_size)
Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost)
-Bridge.UseBPDU, config_parse_bool, 0, offsetof(Network, use_bpdu)
-Bridge.HairPin, config_parse_bool, 0, offsetof(Network, hairpin)
-Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave)
-Bridge.AllowPortToBeRoot, config_parse_bool, 0, offsetof(Network, allow_port_to_be_root)
-Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood)
+Bridge.UseBPDU, config_parse_tristate, 0, offsetof(Network, use_bpdu)
+Bridge.HairPin, config_parse_tristate, 0, offsetof(Network, hairpin)
+Bridge.FastLeave, config_parse_tristate, 0, offsetof(Network, fast_leave)
+Bridge.AllowPortToBeRoot, config_parse_tristate, 0, offsetof(Network, allow_port_to_be_root)
+Bridge.UnicastFlood, config_parse_tristate, 0, offsetof(Network, unicast_flood)
Bridge.Priority, config_parse_bridge_port_priority, 0, offsetof(Network, priority)
BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
@@ -173,6 +179,9 @@ IPv6Prefix.OnLink, config_parse_prefix_flags,
IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0
IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0
IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0
+CAN.BitRate, config_parse_si_size, 0, offsetof(Network, can_bitrate)
+CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point)
+CAN.RestartSec, config_parse_sec, 0, offsetof(Network, can_restart_us)
/* backwards compatibility: do not add new entries to this section */
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 709ae2a0cc..429aac5e6c 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <net/if.h>
@@ -72,8 +54,7 @@ int network_config_section_new(const char *filename, unsigned line, NetworkConfi
strcpy(cs->filename, filename);
cs->line = line;
- *s = cs;
- cs = NULL;
+ *s = TAKE_PTR(cs);
return 0;
}
@@ -123,7 +104,7 @@ void network_apply_anonymize_if_set(Network *network) {
}
static int network_load_one(Manager *manager, const char *filename) {
- _cleanup_network_free_ Network *network = NULL;
+ _cleanup_(network_freep) Network *network = NULL;
_cleanup_fclose_ FILE *file = NULL;
char *d;
const char *dropin_dirname;
@@ -238,9 +219,11 @@ static int network_load_one(Manager *manager, const char *filename) {
network->router_emit_dns = true;
network->router_emit_domains = true;
- network->use_bpdu = true;
- network->allow_port_to_be_root = true;
- network->unicast_flood = true;
+ network->use_bpdu = -1;
+ network->hairpin = -1;
+ network->fast_leave = -1;
+ network->allow_port_to_be_root = -1;
+ network->unicast_flood = -1;
network->priority = LINK_BRIDGE_PORT_PRIORITY_INVALID;
network->lldp_mode = LLDP_MODE_ROUTERS_ONLY;
@@ -248,6 +231,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->llmnr = RESOLVE_SUPPORT_YES;
network->mdns = RESOLVE_SUPPORT_NO;
network->dnssec_mode = _DNSSEC_MODE_INVALID;
+ network->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
network->link_local = ADDRESS_FAMILY_IPV6;
@@ -259,8 +243,11 @@ static int network_load_one(Manager *manager, const char *filename) {
network->duid.type = _DUID_TYPE_INVALID;
network->proxy_arp = -1;
network->arp = -1;
+ network->multicast = -1;
+ network->allmulticast = -1;
network->ipv6_accept_ra_use_dns = true;
network->ipv6_accept_ra_route_table = RT_TABLE_MAIN;
+ network->ipv6_mtu = 0;
dropin_dirname = strjoina(network->name, ".network.d");
@@ -281,7 +268,8 @@ static int network_load_one(Manager *manager, const char *filename) {
"BridgeFDB\0"
"BridgeVLAN\0"
"IPv6PrefixDelegation\0"
- "IPv6Prefix\0",
+ "IPv6Prefix\0"
+ "CAN\0",
config_item_perf_lookup, network_network_gperf_lookup,
CONFIG_PARSE_WARN, network);
if (r < 0)
@@ -364,7 +352,7 @@ void network_free(Network *network) {
free(network->filename);
- free(network->match_mac);
+ set_free_free(network->match_mac);
strv_free(network->match_path);
strv_free(network->match_driver);
strv_free(network->match_type);
@@ -372,6 +360,7 @@ void network_free(Network *network) {
free(network->description);
free(network->dhcp_vendor_class_identifier);
+ strv_free(network->dhcp_user_class);
free(network->dhcp_hostname);
free(network->mac);
@@ -859,7 +848,8 @@ int config_parse_dhcp(
static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
[DHCP_CLIENT_ID_MAC] = "mac",
- [DHCP_CLIENT_ID_DUID] = "duid"
+ [DHCP_CLIENT_ID_DUID] = "duid",
+ [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
@@ -1021,7 +1011,7 @@ int config_parse_timezone(
if (r < 0)
return r;
- if (!timezone_is_valid(tz)) {
+ if (!timezone_is_valid(tz, LOG_ERR)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue);
free(tz);
return 0;
@@ -1397,6 +1387,58 @@ int config_parse_ntp(
return 0;
}
+int config_parse_dhcp_user_class(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char ***l = data;
+ int r;
+
+ assert(l);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *l = strv_free(*l);
+ return 0;
+ }
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+
+ r = extract_first_word(&rvalue, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to split user classes option, ignoring: %s", rvalue);
+ break;
+ }
+ if (r == 0)
+ break;
+
+ if (strlen(w) > 255) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "%s length is not in the range 1-255, ignoring.", w);
+ continue;
+ }
+
+ r = strv_push(l, w);
+ if (r < 0)
+ return log_oom();
+
+ w = NULL;
+ }
+
+ return 0;
+}
+
int config_parse_dhcp_route_table(const char *unit,
const char *filename,
unsigned line,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 7b40ba51e6..2d46d393ac 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -1,44 +1,26 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-bus.h"
#include "udev.h"
#include "condition.h"
+#include "conf-parser.h"
#include "dhcp-identifier.h"
#include "hashmap.h"
-#include "resolve-util.h"
-
-#include "networkd-address.h"
+#include "netdev/netdev.h"
#include "networkd-address-label.h"
+#include "networkd-address.h"
#include "networkd-brvlan.h"
#include "networkd-fdb.h"
-#include "networkd-lldp-tx.h"
#include "networkd-ipv6-proxy-ndp.h"
+#include "networkd-lldp-tx.h"
#include "networkd-radv.h"
#include "networkd-route.h"
#include "networkd-routing-policy-rule.h"
#include "networkd-util.h"
-#include "netdev/netdev.h"
+#include "resolve-util.h"
#define DHCP_ROUTE_METRIC 1024
#define IPV4LL_ROUTE_METRIC 2048
@@ -49,6 +31,11 @@
typedef enum DHCPClientIdentifier {
DHCP_CLIENT_ID_MAC,
DHCP_CLIENT_ID_DUID,
+ /* The following option may not be good for RFC regarding DHCP (3315 and 4361).
+ * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK
+ * requires the client id to be set to a custom string, reported at
+ * https://github.com/systemd/systemd/issues/7828 */
+ DHCP_CLIENT_ID_DUID_ONLY,
_DHCP_CLIENT_ID_MAX,
_DHCP_CLIENT_ID_INVALID = -1,
} DHCPClientIdentifier;
@@ -102,7 +89,6 @@ int network_config_section_new(const char *filename, unsigned line, NetworkConfi
void network_config_section_free(NetworkConfigSection *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
-#define _cleanup_network_config_section_free_ _cleanup_(network_config_section_freep)
typedef struct Manager Manager;
@@ -112,7 +98,7 @@ struct Network {
char *filename;
char *name;
- struct ether_addr *match_mac;
+ Set *match_mac;
char **match_path;
char **match_driver;
char **match_type;
@@ -135,6 +121,7 @@ struct Network {
AddressFamilyBoolean dhcp;
DHCPClientIdentifier dhcp_client_identifier;
char *dhcp_vendor_class_identifier;
+ char **dhcp_user_class;
char *dhcp_hostname;
unsigned dhcp_route_metric;
uint32_t dhcp_route_table;
@@ -186,11 +173,11 @@ struct Network {
char **router_search_domains;
/* Bridge Support */
- bool use_bpdu;
- bool hairpin;
- bool fast_leave;
- bool allow_port_to_be_root;
- bool unicast_flood;
+ int use_bpdu;
+ int hairpin;
+ int fast_leave;
+ int allow_port_to_be_root;
+ int unicast_flood;
uint32_t cost;
uint16_t priority;
@@ -199,6 +186,11 @@ struct Network {
uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN];
uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN];
+ /* CAN support */
+ size_t can_bitrate;
+ unsigned can_sample_point;
+ usec_t can_restart_us;
+
AddressFamilyBoolean ip_forward;
bool ip_masquerade;
@@ -207,6 +199,7 @@ struct Network {
int ipv6_hop_limit;
int ipv6_proxy_ndp;
int proxy_arp;
+ uint32_t ipv6_mtu;
bool ipv6_accept_ra_use_dns;
bool active_slave;
@@ -218,8 +211,10 @@ struct Network {
IPv6PrivacyExtensions ipv6_privacy_extensions;
struct ether_addr *mac;
- size_t mtu;
+ uint32_t mtu;
int arp;
+ int multicast;
+ int allmulticast;
bool unmanaged;
bool configure_without_carrier;
uint32_t iaid;
@@ -261,6 +256,7 @@ struct Network {
ResolveSupport llmnr;
ResolveSupport mdns;
DnssecMode dnssec_mode;
+ DnsOverTlsMode dns_over_tls_mode;
Set *dnssec_negative_trust_anchors;
LIST_FIELDS(Network, networks);
@@ -269,7 +265,6 @@ struct Network {
void network_free(Network *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
-#define _cleanup_network_free_ _cleanup_(network_freep)
int network_load(Manager *manager);
@@ -280,28 +275,28 @@ void network_apply_anonymize_if_set(Network *network);
bool network_has_static_ipv6_addresses(Network *network);
-int config_parse_netdev(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tunnel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_client_identifier(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ipv6token(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ipv6_privacy_extensions(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_timezone(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_server_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_radv_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_radv_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_lldp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
+CONFIG_PARSER_PROTOTYPE(config_parse_netdev);
+CONFIG_PARSER_PROTOTYPE(config_parse_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_tunnel);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
+CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
+CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_route_table);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
+CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
/* Legacy IPv4LL support */
-int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c
index a921d120b3..04a657a87f 100644
--- a/src/network/networkd-radv.c
+++ b/src/network/networkd-radv.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2017 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2017 Intel Corporation. All rights reserved.
***/
#include <netinet/icmp6.h>
@@ -117,7 +102,7 @@ void prefix_free(Prefix *prefix) {
}
int prefix_new(Prefix **ret) {
- Prefix *prefix = NULL;
+ _cleanup_(prefix_freep) Prefix *prefix = NULL;
prefix = new0(Prefix, 1);
if (!prefix)
@@ -126,16 +111,15 @@ int prefix_new(Prefix **ret) {
if (sd_radv_prefix_new(&prefix->radv_prefix) < 0)
return -ENOMEM;
- *ret = prefix;
- prefix = NULL;
+ *ret = TAKE_PTR(prefix);
return 0;
}
int prefix_new_static(Network *network, const char *filename,
unsigned section_line, Prefix **ret) {
- _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
- _cleanup_prefix_free_ Prefix *prefix = NULL;
+ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
+ _cleanup_(prefix_freep) Prefix *prefix = NULL;
int r;
assert(network);
@@ -150,8 +134,7 @@ int prefix_new_static(Network *network, const char *filename,
if (section_line) {
prefix = hashmap_get(network->prefixes_by_section, n);
if (prefix) {
- *ret = prefix;
- prefix = NULL;
+ *ret = TAKE_PTR(prefix);
return 0;
}
@@ -163,8 +146,7 @@ int prefix_new_static(Network *network, const char *filename,
return r;
if (filename) {
- prefix->section = n;
- n = NULL;
+ prefix->section = TAKE_PTR(n);
r = hashmap_put(network->prefixes_by_section, prefix->section,
prefix);
@@ -176,8 +158,7 @@ int prefix_new_static(Network *network, const char *filename,
LIST_APPEND(prefixes, network->static_prefixes, prefix);
network->n_static_prefixes++;
- *ret = prefix;
- prefix = NULL;
+ *ret = TAKE_PTR(prefix);
return 0;
}
@@ -194,7 +175,7 @@ int config_parse_prefix(const char *unit,
void *userdata) {
Network *network = userdata;
- _cleanup_prefix_free_ Prefix *p = NULL;
+ _cleanup_(prefix_freep) Prefix *p = NULL;
uint8_t prefixlen = 64;
union in_addr_union in6addr;
int r;
@@ -236,7 +217,7 @@ int config_parse_prefix_flags(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
- _cleanup_prefix_free_ Prefix *p = NULL;
+ _cleanup_(prefix_freep) Prefix *p = NULL;
int r, val;
assert(filename);
@@ -280,7 +261,7 @@ int config_parse_prefix_lifetime(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
- _cleanup_prefix_free_ Prefix *p = NULL;
+ _cleanup_(prefix_freep) Prefix *p = NULL;
usec_t usec;
int r;
@@ -344,8 +325,7 @@ static int radv_get_ip6dns(Network *network, struct in6_addr **dns,
}
if (addresses) {
- *dns = addresses;
- addresses = NULL;
+ *dns = TAKE_PTR(addresses);
*n_dns = n_addresses;
}
diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h
index 22a169d263..bb88f8a407 100644
--- a/src/network/networkd-radv.h
+++ b/src/network/networkd-radv.h
@@ -2,24 +2,10 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2017 Intel Corporation. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2017 Intel Corporation. All rights reserved.
***/
+#include "conf-parser.h"
#include "networkd-address.h"
#include "networkd-link.h"
@@ -36,17 +22,15 @@ struct Prefix {
int prefix_new(Prefix **ret);
void prefix_free(Prefix *prefix);
-int prefix_new_static(Network *network, const char *filename, unsigned section,
- Prefix **ret);
+int prefix_new_static(Network *network, const char *filename, unsigned section, Prefix **ret);
DEFINE_TRIVIAL_CLEANUP_FUNC(Prefix*, prefix_free);
-#define _cleanup_prefix_free_ _cleanup_(prefix_freep)
-int config_parse_router_prefix_delegation(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_router_preference(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_prefix_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_prefix_lifetime(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation);
+CONFIG_PARSER_PROTOTYPE(config_parse_router_preference);
+CONFIG_PARSER_PROTOTYPE(config_parse_prefix);
+CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags);
+CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime);
int radv_emit_dns(Link *link);
int radv_configure(Link *link);
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 8446feb316..b335fdb1bb 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/icmpv6.h>
@@ -62,7 +44,7 @@ static unsigned routes_max(void) {
}
int route_new(Route **ret) {
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
route = new0(Route, 1);
if (!route)
@@ -76,15 +58,14 @@ int route_new(Route **ret) {
route->lifetime = USEC_INFINITY;
route->quickack = -1;
- *ret = route;
- route = NULL;
+ *ret = TAKE_PTR(route);
return 0;
}
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
- _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
int r;
assert(network);
@@ -98,8 +79,7 @@ int route_new_static(Network *network, const char *filename, unsigned section_li
route = hashmap_get(network->routes_by_section, n);
if (route) {
- *ret = route;
- route = NULL;
+ *ret = TAKE_PTR(route);
return 0;
}
@@ -115,8 +95,7 @@ int route_new_static(Network *network, const char *filename, unsigned section_li
route->protocol = RTPROT_STATIC;
if (filename) {
- route->section = n;
- n = NULL;
+ route->section = TAKE_PTR(n);
r = hashmap_put(network->routes_by_section, route->section, route);
if (r < 0)
@@ -127,8 +106,7 @@ int route_new_static(Network *network, const char *filename, unsigned section_li
LIST_PREPEND(routes, network->static_routes, route);
network->n_static_routes++;
- *ret = route;
- route = NULL;
+ *ret = TAKE_PTR(route);
return 0;
}
@@ -278,7 +256,7 @@ static int route_add_internal(
uint32_t table,
Route **ret) {
- _cleanup_route_free_ Route *route = NULL;
+ _cleanup_(route_freep) Route *route = NULL;
int r;
assert(link);
@@ -327,8 +305,7 @@ int route_add_foreign(
return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret);
}
-int route_add(
- Link *link,
+int route_add(Link *link,
int family,
const union in_addr_union *dst,
unsigned char dst_prefixlen,
@@ -370,13 +347,13 @@ int route_add(
}
void route_update(Route *route,
- const union in_addr_union *src,
- unsigned char src_prefixlen,
- const union in_addr_union *gw,
- const union in_addr_union *prefsrc,
- unsigned char scope,
- unsigned char protocol,
- unsigned char type) {
+ const union in_addr_union *src,
+ unsigned char src_prefixlen,
+ const union in_addr_union *gw,
+ const union in_addr_union *prefsrc,
+ unsigned char scope,
+ unsigned char protocol,
+ unsigned char type) {
assert(route);
assert(src || src_prefixlen == 0);
@@ -391,7 +368,8 @@ void route_update(Route *route,
}
int route_remove(Route *route, Link *link,
- sd_netlink_message_handler_t callback) {
+ sd_netlink_message_handler_t callback) {
+
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
@@ -615,6 +593,13 @@ int route_configure(
if (r < 0)
return log_error_errno(r, "Could not append RTA_PREF attribute: %m");
+ if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
+ r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
+ DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_EXPIRES attribute: %m");
+ }
+
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_error_errno(r, "Could not set route type: %m");
@@ -672,7 +657,7 @@ int route_configure(
/* TODO: drop expiration handling once it can be pushed into the kernel */
route->lifetime = lifetime;
- if (route->lifetime != USEC_INFINITY) {
+ if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) {
r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
route->lifetime, 0, route_expire_handler, route);
if (r < 0)
@@ -680,13 +665,13 @@ int route_configure(
}
sd_event_source_unref(route->expire);
- route->expire = expire;
- expire = NULL;
+ route->expire = TAKE_PTR(expire);
return 0;
}
-int config_parse_gateway(const char *unit,
+int config_parse_gateway(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -698,7 +683,7 @@ int config_parse_gateway(const char *unit,
void *userdata) {
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
+ _cleanup_(route_freep) Route *n = NULL;
union in_addr_union buffer;
int r, f;
@@ -726,12 +711,13 @@ int config_parse_gateway(const char *unit,
n->family = f;
n->gw = buffer;
- n = NULL;
+ TAKE_PTR(n);
return 0;
}
-int config_parse_preferred_src(const char *unit,
+int config_parse_preferred_src(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -743,7 +729,7 @@ int config_parse_preferred_src(const char *unit,
void *userdata) {
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
+ _cleanup_(route_freep) Route *n = NULL;
union in_addr_union buffer;
int r, f;
@@ -766,12 +752,13 @@ int config_parse_preferred_src(const char *unit,
n->family = f;
n->prefsrc = buffer;
- n = NULL;
+ TAKE_PTR(n);
return 0;
}
-int config_parse_destination(const char *unit,
+int config_parse_destination(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -783,7 +770,7 @@ int config_parse_destination(const char *unit,
void *userdata) {
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
+ _cleanup_(route_freep) Route *n = NULL;
union in_addr_union buffer;
unsigned char prefixlen;
int r;
@@ -821,24 +808,24 @@ int config_parse_destination(const char *unit,
} else
assert_not_reached(lvalue);
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_route_priority(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_priority(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
- uint32_t k;
+ _cleanup_(route_freep) Route *n = NULL;
int r;
assert(filename);
@@ -851,31 +838,31 @@ int config_parse_route_priority(const char *unit,
if (r < 0)
return r;
- r = safe_atou32(rvalue, &k);
+ r = safe_atou32(rvalue, &n->priority);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Could not parse route priority \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
- n->priority = k;
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_route_scope(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_scope(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
+ _cleanup_(route_freep) Route *n = NULL;
int r;
assert(filename);
@@ -899,24 +886,24 @@ int config_parse_route_scope(const char *unit,
return 0;
}
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_route_table(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- _cleanup_route_free_ Route *n = NULL;
+int config_parse_route_table(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(route_freep) Route *n = NULL;
Network *network = userdata;
- uint32_t k;
int r;
assert(filename);
@@ -929,32 +916,31 @@ int config_parse_route_table(const char *unit,
if (r < 0)
return r;
- r = safe_atou32(rvalue, &k);
+ r = safe_atou32(rvalue, &n->table);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
- n->table = k;
-
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_gateway_onlink(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_gateway_onlink(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
+ _cleanup_(route_freep) Route *n = NULL;
int r;
assert(filename);
@@ -975,23 +961,24 @@ int config_parse_gateway_onlink(const char *unit,
}
SET_FLAG(n->flags, RTNH_F_ONLINK, r);
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_ipv6_route_preference(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_ipv6_route_preference(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
+ _cleanup_(route_freep) Route *n = NULL;
int r;
r = route_new_static(network, filename, section_line, &n);
@@ -1009,23 +996,24 @@ int config_parse_ipv6_route_preference(const char *unit,
return 0;
}
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_route_protocol(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_protocol(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
+ _cleanup_(route_freep) Route *n = NULL;
int r;
r = route_new_static(network, filename, section_line, &n);
@@ -1046,23 +1034,24 @@ int config_parse_route_protocol(const char *unit,
}
}
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_route_type(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_type(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
- _cleanup_route_free_ Route *n = NULL;
+ _cleanup_(route_freep) Route *n = NULL;
int r;
r = route_new_static(network, filename, section_line, &n);
@@ -1082,22 +1071,23 @@ int config_parse_route_type(const char *unit,
return 0;
}
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_tcp_window(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- _cleanup_route_free_ Route *n = NULL;
+int config_parse_tcp_window(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(route_freep) Route *n = NULL;
Network *network = userdata;
uint64_t k;
int r;
@@ -1128,22 +1118,23 @@ int config_parse_tcp_window(const char *unit,
return 0;
}
- n = NULL;
-
+ TAKE_PTR(n);
return 0;
}
-int config_parse_quickack(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- _cleanup_route_free_ Route *n = NULL;
+int config_parse_quickack(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(route_freep) Route *n = NULL;
Network *network = userdata;
int k, r;
@@ -1164,7 +1155,40 @@ int config_parse_quickack(const char *unit,
}
n->quickack = !!k;
- n = NULL;
+ TAKE_PTR(n);
+ return 0;
+}
+
+int config_parse_route_mtu(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *network = userdata;
+ _cleanup_(route_freep) Route *n = NULL;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = route_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &n->mtu, userdata);
+ if (r < 0)
+ return r;
+ TAKE_PTR(n);
return 0;
}
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
index 6db9d592ea..75da0e3a71 100644
--- a/src/network/networkd-route.h
+++ b/src/network/networkd-route.h
@@ -1,24 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "conf-parser.h"
typedef struct Route Route;
typedef struct NetworkConfigSection NetworkConfigSection;
@@ -73,17 +57,17 @@ void route_update(Route *route, const union in_addr_union *src, unsigned char sr
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
-#define _cleanup_route_free_ _cleanup_(route_freep)
-
-int config_parse_gateway(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_preferred_src(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_destination(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_scope(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_gateway_onlink(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ipv6_route_preference(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_protocol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tcp_window(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_quickack(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
+CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
+CONFIG_PARSER_PROTOTYPE(config_parse_destination);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_priority);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_scope);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_table);
+CONFIG_PARSER_PROTOTYPE(config_parse_gateway_onlink);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_route_preference);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
+CONFIG_PARSER_PROTOTYPE(config_parse_quickack);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c
index fdbaec58eb..650ea0af52 100644
--- a/src/network/networkd-routing-policy-rule.c
+++ b/src/network/networkd-routing-policy-rule.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
#include <linux/fib_rules.h>
@@ -251,7 +233,7 @@ static int routing_policy_rule_add_internal(Manager *m,
char *oif,
RoutingPolicyRule **ret) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *rule = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
int r;
assert_return(rules, -EINVAL);
@@ -320,7 +302,7 @@ int routing_policy_rule_add_foreign(Manager *m,
}
static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(m);
@@ -392,8 +374,8 @@ int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *lin
}
static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *rule = NULL;
- _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
+ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
int r;
assert(network);
@@ -406,8 +388,7 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
rule = hashmap_get(network->rules_by_section, n);
if (rule) {
- *ret = rule;
- rule = NULL;
+ *ret = TAKE_PTR(rule);
return 0;
}
@@ -427,14 +408,13 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
LIST_APPEND(rules, network->rules, rule);
network->n_rules++;
- *ret = rule;
- rule = NULL;
+ *ret = TAKE_PTR(rule);
return 0;
}
int link_routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- _cleanup_link_unref_ Link *link = userdata;
+ _cleanup_(link_unrefp) Link *link = userdata;
int r;
assert(rtnl);
@@ -607,7 +587,7 @@ int config_parse_routing_policy_rule_tos(
void *data,
void *userdata) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *n = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@@ -644,7 +624,7 @@ int config_parse_routing_policy_rule_priority(
void *data,
void *userdata) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *n = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@@ -681,7 +661,7 @@ int config_parse_routing_policy_rule_table(
void *data,
void *userdata) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *n = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@@ -718,7 +698,7 @@ int config_parse_routing_policy_rule_fwmark_mask(
void *data,
void *userdata) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *n = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@@ -755,7 +735,7 @@ int config_parse_routing_policy_rule_prefix(
void *data,
void *userdata) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *n = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
Network *network = userdata;
union in_addr_union buffer;
uint8_t prefixlen;
@@ -808,7 +788,7 @@ int config_parse_routing_policy_rule_device(
void *data,
void *userdata) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *n = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@@ -857,8 +837,7 @@ static int routing_policy_rule_read_full_file(const char *state_file, char **ret
if (size <= 0)
return -ENODATA;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return size;
}
@@ -956,7 +935,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
return r;
STRV_FOREACH(i, l) {
- _cleanup_routing_policy_rule_free_ RoutingPolicyRule *rule = NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
p = startswith(*i, "RULE=");
if (!p)
diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h
index 48353b9d10..f4a0d5138f 100644
--- a/src/network/networkd-routing-policy-rule.h
+++ b/src/network/networkd-routing-policy-rule.h
@@ -1,29 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <inttypes.h>
#include <stdbool.h>
#include "in-addr-util.h"
+#include "conf-parser.h"
typedef struct RoutingPolicyRule RoutingPolicyRule;
@@ -65,7 +48,6 @@ int routing_policy_rule_new(RoutingPolicyRule **ret);
void routing_policy_rule_free(RoutingPolicyRule *rule);
DEFINE_TRIVIAL_CLEANUP_FUNC(RoutingPolicyRule*, routing_policy_rule_free);
-#define _cleanup_routing_policy_rule_free_ _cleanup_(routing_policy_rule_freep)
int routing_policy_rule_configure(RoutingPolicyRule *address, Link *link, sd_netlink_message_handler_t callback, bool update);
int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, sd_netlink_message_handler_t callback);
@@ -83,9 +65,9 @@ int routing_policy_serialize_rules(Set *rules, FILE *f);
int routing_policy_load_rules(const char *state_file, Set **rules);
void routing_policy_rule_purge(Manager *m, Link *link);
-int config_parse_routing_policy_rule_tos(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data,void *userdata);
-int config_parse_routing_policy_rule_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_routing_policy_rule_fwmark_mask(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_routing_policy_rule_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_routing_policy_rule_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data,void *userdata);
-int config_parse_routing_policy_rule_device(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data,void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_tos);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_table);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_fwmark_mask);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_prefix);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_priority);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device);
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c
index b9c533fcc7..9b6bc12858 100644
--- a/src/network/networkd-util.c
+++ b/src/network/networkd-util.c
@@ -1,23 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "condition.h"
#include "conf-parser.h"
#include "networkd-util.h"
#include "parse-util.h"
@@ -99,3 +82,23 @@ int config_parse_address_family_boolean_with_kernel(
return 0;
}
+
+/* Router lifetime can be set with netlink interface since kernel >= 4.5
+ * so for the supported kernel we dont need to expire routes in userspace */
+int kernel_route_expiration_supported(void) {
+ static int cached = -1;
+ int r;
+
+ if (cached < 0) {
+ Condition c = {
+ .type = CONDITION_KERNEL_VERSION,
+ .parameter = (char *) ">= 4.5"
+ };
+ r = condition_test(&c);
+ if (r < 0)
+ return r;
+
+ cached = r;
+ }
+ return cached;
+}
diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h
index 69ea93ad08..0fb41caaf6 100644
--- a/src/network/networkd-util.h
+++ b/src/network/networkd-util.h
@@ -1,25 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "conf-parser.h"
#include "macro.h"
typedef enum AddressFamilyBoolean {
@@ -32,8 +15,10 @@ typedef enum AddressFamilyBoolean {
_ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
} AddressFamilyBoolean;
-int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_family_boolean_with_kernel(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_family_boolean);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_family_boolean_with_kernel);
const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
+
+int kernel_route_expiration_supported(void);
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 79c15d4111..b59b308141 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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"
#include "sd-event.h"
@@ -29,7 +11,7 @@
int main(int argc, char *argv[]) {
sd_event *event = NULL;
- _cleanup_manager_free_ Manager *m = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
const char *user = "systemd-network";
uid_t uid;
gid_t gid;
@@ -56,7 +38,7 @@ int main(int argc, char *argv[]) {
/* Create runtime directory. This is not necessary when networkd is
* started with "RuntimeDirectory=systemd/netif", or after
* systemd-tmpfiles-setup.service. */
- r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid, false);
+ r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid, MKDIR_WARN_MODE);
if (r < 0)
log_warning_errno(r, "Could not create runtime directory: %m");
@@ -75,15 +57,15 @@ int main(int argc, char *argv[]) {
/* Always create the directories people can create inotify watches in.
* It is necessary to create the following subdirectories after drop_privileges()
* to support old kernels not supporting AmbientCapabilities=. */
- r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid, false);
+ r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid, MKDIR_WARN_MODE);
if (r < 0)
log_warning_errno(r, "Could not create runtime directory 'links': %m");
- r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid, false);
+ r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid, MKDIR_WARN_MODE);
if (r < 0)
log_warning_errno(r, "Could not create runtime directory 'leases': %m");
- r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid, false);
+ r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid, MKDIR_WARN_MODE);
if (r < 0)
log_warning_errno(r, "Could not create runtime directory 'lldp': %m");
diff --git a/src/network/test-network-tables.c b/src/network/test-network-tables.c
index eee91d11d2..11cd7faa8b 100644
--- a/src/network/test-network-tables.c
+++ b/src/network/test-network-tables.c
@@ -1,28 +1,42 @@
#include "dhcp6-internal.h"
#include "dhcp6-protocol.h"
#include "ethtool-util.h"
-#include "netlink-internal.h"
#include "netdev/bond.h"
#include "netdev/ipvlan.h"
#include "netdev/macvlan.h"
+#include "netdev/tunnel.h"
+#include "netlink-internal.h"
#include "networkd-link.h"
+#include "networkd-network.h"
#include "networkd-util.h"
#include "test-tables.h"
int main(int argc, char **argv) {
- test_table(bond_mode, NETDEV_BOND_MODE);
- /* test_table(link_state, LINK_STATE); — not a reversible mapping */
- test_table(link_operstate, LINK_OPERSTATE);
test_table(address_family_boolean, ADDRESS_FAMILY_BOOLEAN);
- test_table(netdev_kind, NETDEV_KIND);
+ test_table(bond_ad_select, NETDEV_BOND_AD_SELECT);
+ test_table(bond_arp_all_targets, NETDEV_BOND_ARP_ALL_TARGETS);
+ test_table(bond_arp_validate, NETDEV_BOND_ARP_VALIDATE);
+ test_table(bond_fail_over_mac, NETDEV_BOND_FAIL_OVER_MAC);
+ test_table(bond_lacp_rate, NETDEV_BOND_LACP_RATE);
+ test_table(bond_mode, NETDEV_BOND_MODE);
+ test_table(bond_primary_reselect, NETDEV_BOND_PRIMARY_RESELECT);
+ test_table(bond_xmit_hash_policy, NETDEV_BOND_XMIT_HASH_POLICY);
test_table(dhcp6_message_status, DHCP6_STATUS);
+ test_table(dhcp_use_domains, DHCP_USE_DOMAINS);
test_table(duplex, DUP);
- test_table(wol, WOL);
+ test_table(ip6tnl_mode, NETDEV_IP6_TNL_MODE);
+ test_table(ipv6_privacy_extensions, IPV6_PRIVACY_EXTENSIONS);
+ test_table(ipvlan_flags, NETDEV_IPVLAN_FLAGS);
+ test_table(link_operstate, LINK_OPERSTATE);
+ /* test_table(link_state, LINK_STATE); — not a reversible mapping */
+ test_table(lldp_mode, LLDP_MODE);
+ test_table(netdev_kind, NETDEV_KIND);
test_table(nl_union_link_info_data, NL_UNION_LINK_INFO_DATA);
+ test_table(wol, WOL);
- test_table_sparse(macvlan_mode, NETDEV_MACVLAN_MODE);
- test_table_sparse(ipvlan_mode, NETDEV_IPVLAN_MODE);
test_table_sparse(dhcp6_message_type, DHCP6_MESSAGE);
+ test_table_sparse(ipvlan_mode, NETDEV_IPVLAN_MODE);
+ test_table_sparse(macvlan_mode, NETDEV_MACVLAN_MODE);
return EXIT_SUCCESS;
}
diff --git a/src/network/test-network.c b/src/network/test-network.c
index f3e8f508f3..5349b668be 100644
--- a/src/network/test-network.c
+++ b/src/network/test-network.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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/param.h>
@@ -146,7 +128,7 @@ static void test_network_get(Manager *manager, struct udev_device *loopback) {
}
static void test_address_equality(void) {
- _cleanup_address_free_ Address *a1 = NULL, *a2 = NULL;
+ _cleanup_(address_freep) Address *a1 = NULL, *a2 = NULL;
assert_se(address_new(&a1) >= 0);
assert_se(address_new(&a2) >= 0);
@@ -236,10 +218,10 @@ static void test_dhcp_hostname_shorten_overlong(void) {
}
int main(void) {
- _cleanup_manager_free_ Manager *manager = NULL;
+ _cleanup_(manager_freep) Manager *manager = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_udev_device_unref_ struct udev_device *loopback = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *loopback = NULL;
int r;
test_deserialize_in_addr();
diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c
index 530bbf8636..fc1646f4bf 100644
--- a/src/network/test-networkd-conf.c
+++ b/src/network/test-networkd-conf.c
@@ -1,32 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "ether-addr-util.h"
#include "hexdecoct.h"
#include "log.h"
#include "macro.h"
+#include "set.h"
#include "string-util.h"
-#include "ether-addr-util.h"
+#include "network-internal.h"
#include "networkd-conf.h"
#include "networkd-network.h"
-#include "network-internal.h"
static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected) {
DUIDType actual = 0;
@@ -71,13 +54,29 @@ static void test_config_parse_hwaddr_one(const char *rvalue, int ret, const stru
assert_se(ret == r);
if (expected) {
assert_se(actual);
- assert(ether_addr_equal(expected, actual));
- } else {
+ assert_se(ether_addr_equal(expected, actual));
+ } else
assert_se(actual == NULL);
- }
+
free(actual);
}
+static void test_config_parse_hwaddrs_one(const char *rvalue, const struct ether_addr* list, size_t n) {
+ _cleanup_set_free_free_ Set *s = NULL;
+ size_t m;
+
+ assert_se(config_parse_hwaddrs("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &s, NULL) == 0);
+ assert_se(set_size(s) == n);
+
+ for (m = 0; m < n; m++) {
+ _cleanup_free_ struct ether_addr *q = NULL;
+
+ assert_se(q = set_remove(s, &list[m]));
+ }
+
+ assert_se(set_size(s) == 0);
+}
+
#define BYTES_0_128 "0:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:3e:3f:40:41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54:55:56:57:58:59:5a:5b:5c:5d:5e:5f:60:61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:78:79:7a:7b:7c:7d:7e:7f:80"
#define BYTES_1_128 {0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80}
@@ -103,12 +102,13 @@ static void test_config_parse_hwaddr(void) {
{ .ether_addr_octet = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } },
{ .ether_addr_octet = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } },
};
+
test_config_parse_hwaddr_one("", 0, NULL);
test_config_parse_hwaddr_one("no:ta:ma:ca:dd:re", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:fx", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff", 0, &t[0]);
test_config_parse_hwaddr_one(" aa:bb:cc:dd:ee:ff", 0, &t[0]);
- test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\n", 0, &t[0]);
+ test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\n", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\nxxx", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc: dd:ee:ff", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:d d:ee:ff", 0, NULL);
@@ -129,6 +129,36 @@ static void test_config_parse_hwaddr(void) {
test_config_parse_hwaddr_one("aabbccddee:ff", 0, NULL);
test_config_parse_hwaddr_one("012345.6789ab", 0, NULL);
test_config_parse_hwaddr_one("123.4567.89ab", 0, &t[1]);
+
+ test_config_parse_hwaddrs_one("", t, 0);
+ test_config_parse_hwaddrs_one("no:ta:ma:ca:dd:re", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:fx", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff", t, 1);
+ test_config_parse_hwaddrs_one(" aa:bb:cc:dd:ee:ff", t, 1);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff \t\n", t, 1);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff \t\nxxx", t, 1);
+ test_config_parse_hwaddrs_one("aa:bb:cc: dd:ee:ff", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:d d:ee:ff", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee", t, 0);
+ test_config_parse_hwaddrs_one("9:aa:bb:cc:dd:ee:ff", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff:gg", t, 0);
+ test_config_parse_hwaddrs_one("aa:Bb:CC:dd:ee:ff", t, 1);
+ test_config_parse_hwaddrs_one("01:23:45:67:89:aB", &t[1], 1);
+ test_config_parse_hwaddrs_one("1:23:45:67:89:aB", &t[1], 1);
+ test_config_parse_hwaddrs_one("aa-bb-cc-dd-ee-ff", t, 1);
+ test_config_parse_hwaddrs_one("AA-BB-CC-DD-EE-FF", t, 1);
+ test_config_parse_hwaddrs_one("01-23-45-67-89-ab", &t[1], 1);
+ test_config_parse_hwaddrs_one("aabb.ccdd.eeff", t, 1);
+ test_config_parse_hwaddrs_one("0123.4567.89ab", &t[1], 1);
+ test_config_parse_hwaddrs_one("123.4567.89ab.", t, 0);
+ test_config_parse_hwaddrs_one("aabbcc.ddeeff", t, 0);
+ test_config_parse_hwaddrs_one("aabbccddeeff", t, 0);
+ test_config_parse_hwaddrs_one("aabbccddee:ff", t, 0);
+ test_config_parse_hwaddrs_one("012345.6789ab", t, 0);
+ test_config_parse_hwaddrs_one("123.4567.89ab", &t[1], 1);
+
+ test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:ff 01-23-45-67-89-ab aa:Bb:CC:dd:ee:ff", t, 2);
+ test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:fx hogehoge 01-23-45-67-89-ab aaaa aa:Bb:CC:dd:ee:ff", t, 2);
}
int main(int argc, char **argv) {
diff --git a/src/network/test-routing-policy-rule.c b/src/network/test-routing-policy-rule.c
index 3bbdd25b76..9920f516b7 100644
--- a/src/network/test-routing-policy-rule.c
+++ b/src/network/test-routing-policy-rule.c
@@ -1,22 +1,5 @@
/***
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "fd-util.h"
diff --git a/src/network/wait-online/link.c b/src/network/wait-online/link.c
index f0cb70ab4c..87d54fe654 100644
--- a/src/network/wait-online/link.c
+++ b/src/network/wait-online/link.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-network.h"
diff --git a/src/network/wait-online/link.h b/src/network/wait-online/link.h
index ab623ff4de..f1096c99d9 100644
--- a/src/network/wait-online/link.h
+++ b/src/network/wait-online/link.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-netlink.h"
diff --git a/src/network/wait-online/manager.c b/src/network/wait-online/manager.c
index 05f030dbe7..ccda93babe 100644
--- a/src/network/wait-online/manager.c
+++ b/src/network/wait-online/manager.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/ether.h>
#include <linux/if.h>
@@ -303,8 +285,7 @@ int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout)
if (r < 0)
return r;
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
diff --git a/src/network/wait-online/manager.h b/src/network/wait-online/manager.h
index 7a8c4ea473..21f0381dda 100644
--- a/src/network/wait-online/manager.h
+++ b/src/network/wait-online/manager.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-event.h"
#include "sd-netlink.h"
diff --git a/src/network/wait-online/wait-online.c b/src/network/wait-online/wait-online.c
index 7b13a5d879..a96b2c8fe5 100644
--- a/src/network/wait-online/wait-online.c
+++ b/src/network/wait-online/wait-online.c
@@ -1,23 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
diff --git a/src/notify/notify.c b/src/notify/notify.c
index d58a45cdd2..e928094d9a 100644
--- a/src/notify/notify.c
+++ b/src/notify/notify.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
diff --git a/src/nspawn/meson.build b/src/nspawn/meson.build
index b1e7134bef..be54ba36c5 100644
--- a/src/nspawn/meson.build
+++ b/src/nspawn/meson.build
@@ -1,21 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-systemd_nspawn_sources = files('''
+libnspawn_core_sources = files('''
nspawn-cgroup.c
nspawn-cgroup.h
nspawn-def.h
@@ -37,7 +22,6 @@ systemd_nspawn_sources = files('''
nspawn-setuid.h
nspawn-stub-pid1.c
nspawn-stub-pid1.h
- nspawn.c
'''.split())
nspawn_gperf_c = custom_target(
@@ -46,13 +30,27 @@ nspawn_gperf_c = custom_target(
output : 'nspawn-gperf.c',
command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
-systemd_nspawn_sources += [nspawn_gperf_c]
+libnspawn_core_sources += [nspawn_gperf_c]
+
+libnspawn_core = static_library(
+ 'nspawn-core',
+ libnspawn_core_sources,
+ include_directories : includes,
+ dependencies : [libacl,
+ libseccomp,
+ libselinux])
+
+systemd_nspawn_sources = files('nspawn.c')
tests += [
- [['src/nspawn/test-patch-uid.c',
- 'src/nspawn/nspawn-patch-uid.c',
- 'src/nspawn/nspawn-patch-uid.h'],
- [libshared],
+ [['src/nspawn/test-nspawn-tables.c'],
+ [libnspawn_core,
+ libshared],
+ []],
+
+ [['src/nspawn/test-patch-uid.c'],
+ [libnspawn_core,
+ libshared],
[libacl],
'', 'manual'],
]
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
index d51585a652..d8a39a6959 100644
--- a/src/nspawn/nspawn-cgroup.c
+++ b/src/nspawn/nspawn-cgroup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/mount.h>
@@ -154,44 +136,53 @@ finish:
return r;
}
-int create_subcgroup(pid_t pid, CGroupUnified unified_requested) {
+int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested) {
_cleanup_free_ char *cgroup = NULL;
- const char *child;
- int r;
CGroupMask supported;
+ const char *payload;
+ int r;
- /* In the unified hierarchy inner nodes may only contain
- * subgroups, but not processes. Hence, if we running in the
- * unified hierarchy and the container does the same, and we
- * did not create a scope unit for the container move us and
- * the container into two separate subcgroups. */
-
- if (unified_requested == CGROUP_UNIFIED_NONE)
- return 0;
-
- r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
- if (r < 0)
- return log_error_errno(r, "Failed to determine whether the systemd controller is unified: %m");
- if (r == 0)
- return 0;
+ assert(pid > 1);
+
+ /* In the unified hierarchy inner nodes may only contain subgroups, but not processes. Hence, if we running in
+ * the unified hierarchy and the container does the same, and we did not create a scope unit for the container
+ * move us and the container into two separate subcgroups.
+ *
+ * Moreover, container payloads such as systemd try to manage the cgroup they run in in full (i.e. including
+ * its attributes), while the host systemd will only delegate cgroups for children of the cgroup created for a
+ * delegation unit, instead of the cgroup itself. This means, if we'd pass on the cgroup allocated from the
+ * host systemd directly to the payload, the host and payload systemd might fight for the cgroup
+ * attributes. Hence, let's insert an intermediary cgroup to cover that case too.
+ *
+ * Note that we only bother with the main hierarchy here, not with any secondary ones. On the unified setup
+ * that's fine because there's only one hiearchy anyway and controllers are enabled directly on it. On the
+ * legacy setup, this is fine too, since delegation of controllers is generally not safe there, hence we won't
+ * do it. */
r = cg_mask_supported(&supported);
if (r < 0)
return log_error_errno(r, "Failed to determine supported controllers: %m");
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
+ if (keep_unit)
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
+ else
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
if (r < 0)
return log_error_errno(r, "Failed to get our control group: %m");
- child = strjoina(cgroup, "/payload");
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, pid);
+ payload = strjoina(cgroup, "/payload");
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, payload, pid);
if (r < 0)
- return log_error_errno(r, "Failed to create %s subcgroup: %m", child);
+ return log_error_errno(r, "Failed to create %s subcgroup: %m", payload);
- child = strjoina(cgroup, "/supervisor");
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to create %s subcgroup: %m", child);
+ if (keep_unit) {
+ const char *supervisor;
+
+ supervisor = strjoina(cgroup, "/supervisor");
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, supervisor, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create %s subcgroup: %m", supervisor);
+ }
/* Try to enable as many controllers as possible for the new payload. */
(void) cg_enable_everywhere(supported, supported, cgroup);
diff --git a/src/nspawn/nspawn-cgroup.h b/src/nspawn/nspawn-cgroup.h
index 3855e5b4ea..6783c3a39f 100644
--- a/src/nspawn/nspawn-cgroup.h
+++ b/src/nspawn/nspawn-cgroup.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
@@ -27,4 +8,4 @@
int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
-int create_subcgroup(pid_t pid, CGroupUnified unified_requested);
+int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested);
diff --git a/src/nspawn/nspawn-def.h b/src/nspawn/nspawn-def.h
index 43a19d84f5..9b54cda2f7 100644
--- a/src/nspawn/nspawn-def.h
+++ b/src/nspawn/nspawn-def.h
@@ -1,24 +1,5 @@
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
/* While we are chmod()ing a directory tree, we set the top-level UID base to this "busy" base, so that we can always
diff --git a/src/nspawn/nspawn-expose-ports.c b/src/nspawn/nspawn-expose-ports.c
index 98eb85081e..07da7922f1 100644
--- a/src/nspawn/nspawn-expose-ports.c
+++ b/src/nspawn/nspawn-expose-ports.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-netlink.h"
@@ -239,8 +221,7 @@ int expose_port_watch_rtnl(
if (r < 0)
return log_error_errno(r, "Failed to add to even loop: %m");
- *ret = rtnl;
- rtnl = NULL;
+ *ret = TAKE_PTR(rtnl);
return 0;
}
diff --git a/src/nspawn/nspawn-expose-ports.h b/src/nspawn/nspawn-expose-ports.h
index bd88343a02..7ed7bee03f 100644
--- a/src/nspawn/nspawn-expose-ports.h
+++ b/src/nspawn/nspawn-expose-ports.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include "sd-event.h"
diff --git a/src/nspawn/nspawn-gperf.gperf b/src/nspawn/nspawn-gperf.gperf
index ea66971fac..6029686ee9 100644
--- a/src/nspawn/nspawn-gperf.gperf
+++ b/src/nspawn/nspawn-gperf.gperf
@@ -18,35 +18,58 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Exec.Boot, config_parse_boot, 0, 0
-Exec.ProcessTwo, config_parse_pid2, 0, 0
-Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
-Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
-Exec.User, config_parse_string, 0, offsetof(Settings, user)
-Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
-Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
-Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
-Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
-Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id)
-Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory)
-Exec.PivotRoot, config_parse_pivot_root, 0, 0
-Exec.PrivateUsers, config_parse_private_users, 0, 0
-Exec.NotifyReady, config_parse_bool, 0, offsetof(Settings, notify_ready)
-Exec.SystemCallFilter, config_parse_syscall_filter,0, 0,
-Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
-Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
-Files.Bind, config_parse_bind, 0, 0
-Files.BindReadOnly, config_parse_bind, 1, 0
-Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0
-Files.Overlay, config_parse_overlay, 0, 0
-Files.OverlayReadOnly, config_parse_overlay, 1, 0
-Files.PrivateUsersChown, config_parse_tristate, 0, offsetof(Settings, userns_chown)
-Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
-Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
-Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
-Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
-Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
-Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
-Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge)
-Network.Zone, config_parse_network_zone, 0, 0
-Network.Port, config_parse_expose_port, 0, 0
+Exec.Boot, config_parse_boot, 0, 0
+Exec.ProcessTwo, config_parse_pid2, 0, 0
+Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
+Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
+Exec.User, config_parse_string, 0, offsetof(Settings, user)
+Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
+Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
+Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
+Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
+Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id)
+Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory)
+Exec.PivotRoot, config_parse_pivot_root, 0, 0
+Exec.PrivateUsers, config_parse_private_users, 0, 0
+Exec.NotifyReady, config_parse_bool, 0, offsetof(Settings, notify_ready)
+Exec.SystemCallFilter, config_parse_syscall_filter, 0, 0,
+Exec.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof(Settings, rlimit)
+Exec.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof(Settings, rlimit)
+Exec.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof(Settings, rlimit)
+Exec.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof(Settings, rlimit)
+Exec.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof(Settings, rlimit)
+Exec.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof(Settings, rlimit)
+Exec.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof(Settings, rlimit)
+Exec.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof(Settings, rlimit)
+Exec.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof(Settings, rlimit)
+Exec.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof(Settings, rlimit)
+Exec.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof(Settings, rlimit)
+Exec.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof(Settings, rlimit)
+Exec.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof(Settings, rlimit)
+Exec.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof(Settings, rlimit)
+Exec.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof(Settings, rlimit)
+Exec.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof(Settings, rlimit)
+Exec.Hostname, config_parse_hostname, 0, offsetof(Settings, hostname)
+Exec.NoNewPrivileges, config_parse_tristate, 0, offsetof(Settings, no_new_privileges)
+Exec.OOMScoreAdjust, config_parse_oom_score_adjust, 0, 0
+Exec.CPUAffinity, config_parse_cpu_affinity, 0, 0
+Exec.ResolvConf, config_parse_resolv_conf, 0, offsetof(Settings, resolv_conf)
+Exec.LinkJournal, config_parse_link_journal, 0, 0
+Exec.Timezone, config_parse_timezone, 0, offsetof(Settings, timezone)
+Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
+Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
+Files.Bind, config_parse_bind, 0, 0
+Files.BindReadOnly, config_parse_bind, 1, 0
+Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0
+Files.Overlay, config_parse_overlay, 0, 0
+Files.OverlayReadOnly, config_parse_overlay, 1, 0
+Files.PrivateUsersChown, config_parse_tristate, 0, offsetof(Settings, userns_chown)
+Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
+Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
+Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
+Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
+Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
+Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
+Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge)
+Network.Zone, config_parse_network_zone, 0, 0
+Network.Port, config_parse_expose_port, 0, 0
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index 0ee69114b2..b5df65e2a4 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/mount.h>
#include <linux/magic.h>
@@ -40,7 +22,7 @@
#include "user-util.h"
#include "util.h"
-CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
+CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t) {
CustomMount *c, *ret;
assert(l);
@@ -61,8 +43,8 @@ CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
return ret;
}
-void custom_mount_free_all(CustomMount *l, unsigned n) {
- unsigned i;
+void custom_mount_free_all(CustomMount *l, size_t n) {
+ size_t i;
for (i = 0; i < n; i++) {
CustomMount *m = l + i;
@@ -123,8 +105,8 @@ static char *resolve_source_path(const char *dest, const char *source) {
return strdup(source);
}
-int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
- unsigned i;
+int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n) {
+ size_t i;
int r;
/* Prepare all custom mounts. This will make source we know all temporary directories. This is called in the
@@ -146,8 +128,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
if (!s)
return log_oom();
- free(m->source);
- m->source = s;
+ free_and_replace(m->source, s);
} else {
/* No source specified? In that case, use a throw-away temporary directory in /var/tmp */
@@ -178,8 +159,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
if (!s)
return log_oom();
- free(*j);
- *j = s;
+ free_and_replace(*j, s);
}
if (m->work_dir) {
@@ -189,8 +169,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
if (!s)
return log_oom();
- free(m->work_dir);
- m->work_dir = s;
+ free_and_replace(m->work_dir, s);
} else {
assert(m->source);
@@ -206,7 +185,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
return 0;
}
-int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only) {
+int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) {
_cleanup_free_ char *source = NULL, *destination = NULL, *opts = NULL;
const char *p = s;
CustomMount *m;
@@ -252,7 +231,7 @@ int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only
return 0;
}
-int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) {
+int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s) {
_cleanup_free_ char *path = NULL, *opts = NULL;
const char *p = s;
CustomMount *m;
@@ -282,14 +261,13 @@ int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) {
if (!m)
return -ENOMEM;
- m->destination = path;
- m->options = opts;
+ m->destination = TAKE_PTR(path);
+ m->options = TAKE_PTR(opts);
- path = opts = NULL;
return 0;
}
-int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only) {
+int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) {
_cleanup_free_ char *upper = NULL, *destination = NULL;
_cleanup_strv_free_ char **lower = NULL;
CustomMount *m;
@@ -308,8 +286,7 @@ int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_o
!source_path_is_valid(lower[1]))
return -EINVAL;
- upper = lower[1];
- lower[1] = NULL;
+ upper = TAKE_PTR(lower[1]);
destination = strdup(upper[0] == '+' ? upper+1 : upper); /* take the destination without "+" prefix */
if (!destination)
@@ -321,8 +298,7 @@ int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_o
* the "upper", and all before that the "lower" directories. */
destination = lower[k - 1];
- upper = lower[k - 2];
- lower[k - 2] = NULL;
+ upper = TAKE_PTR(lower[k - 2]);
STRV_FOREACH(i, lower)
if (!source_path_is_valid(*i))
@@ -343,14 +319,11 @@ int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_o
if (!m)
return -ENOMEM;
- m->destination = destination;
- m->source = upper;
- m->lower = lower;
+ m->destination = TAKE_PTR(destination);
+ m->source = TAKE_PTR(upper);
+ m->lower = TAKE_PTR(lower);
m->read_only = read_only;
- upper = destination = NULL;
- lower = NULL;
-
return 0;
}
@@ -530,6 +503,18 @@ int mount_all(const char *dest,
uid_t uid_shift, uid_t uid_range,
const char *selinux_apifs_context) {
+#define PROC_INACCESSIBLE(path) \
+ { NULL, (path), NULL, NULL, MS_BIND, \
+ MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_INACCESSIBLE_REG }, /* Bind mount first ... */ \
+ { NULL, (path), NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, \
+ MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO } /* Then, make it r/o */
+
+#define PROC_READ_ONLY(path) \
+ { (path), (path), NULL, NULL, MS_BIND, \
+ MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */ \
+ { NULL, (path), NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, \
+ MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO } /* Then, make it r/o */
+
typedef struct MountPoint {
const char *what;
const char *where;
@@ -540,39 +525,72 @@ int mount_all(const char *dest,
} MountPoint;
static const MountPoint mount_table[] = {
- /* inner child mounts */
- { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_IN_USERNS },
- { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
- { "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS }, /* (except for this) */
- { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
- { "/proc/sysrq-trigger", "/proc/sysrq-trigger", NULL, NULL, MS_BIND, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
- { NULL, "/proc/sysrq-trigger", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
-
- /* outer child mounts */
- { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
- { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
- { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */
- { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL }, /* skipped if above was mounted */
-
- { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, MOUNT_FATAL },
- { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
- { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
+ /* First we list inner child mounts (i.e. mounts applied *after* entering user namespacing) */
+ { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ MOUNT_FATAL|MOUNT_IN_USERNS },
+
+ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND,
+ MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
+
+ { "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND,
+ MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS }, /* (except for this) */
+
+ { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
+ MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
+
+ /* Make these files inaccessible to container payloads: they potentially leak information about kernel
+ * internals or the host's execution environment to the container */
+ PROC_INACCESSIBLE("/proc/kallsyms"),
+ PROC_INACCESSIBLE("/proc/kcore"),
+ PROC_INACCESSIBLE("/proc/keys"),
+ PROC_INACCESSIBLE("/proc/sysrq-trigger"),
+ PROC_INACCESSIBLE("/proc/timer_list"),
+
+ /* Make these directories read-only to container payloads: they show hardware information, and in some
+ * cases contain tunables the container really shouldn't have access to. */
+ PROC_READ_ONLY("/proc/acpi"),
+ PROC_READ_ONLY("/proc/apm"),
+ PROC_READ_ONLY("/proc/asound"),
+ PROC_READ_ONLY("/proc/bus"),
+ PROC_READ_ONLY("/proc/fs"),
+ PROC_READ_ONLY("/proc/irq"),
+ PROC_READ_ONLY("/proc/scsi"),
+
+ /* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing) */
+ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
+ MOUNT_FATAL },
+ { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
+ { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */
+ { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ MOUNT_FATAL }, /* skipped if above was mounted */
+ { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME,
+ MOUNT_FATAL },
+ { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
+ MOUNT_FATAL },
+ { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
+ MOUNT_FATAL },
+
#if HAVE_SELINUX
- { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, 0 }, /* Bind mount first */
- { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, 0 }, /* Then, make it r/o */
+ { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND,
+ 0 }, /* Bind mount first */
+ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
+ 0 }, /* Then, make it r/o */
#endif
};
- unsigned k;
- int r;
+ _cleanup_(unlink_and_freep) char *inaccessible = NULL;
bool use_userns = (mount_settings & MOUNT_USE_USERNS);
bool netns = (mount_settings & MOUNT_APPLY_APIVFS_NETNS);
bool ro = (mount_settings & MOUNT_APPLY_APIVFS_RO);
bool in_userns = (mount_settings & MOUNT_IN_USERNS);
+ size_t k;
+ int r;
for (k = 0; k < ELEMENTSOF(mount_table); k++) {
_cleanup_free_ char *where = NULL, *options = NULL;
- const char *o;
+ const char *o, *what;
bool fatal = (mount_table[k].mount_settings & MOUNT_FATAL);
if (in_userns != (bool)(mount_table[k].mount_settings & MOUNT_IN_USERNS))
@@ -588,12 +606,32 @@ int mount_all(const char *dest,
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where);
+ if (mount_table[k].mount_settings & MOUNT_INACCESSIBLE_REG) {
+
+ if (!inaccessible) {
+ _cleanup_free_ char *np = NULL;
+
+ r = tempfn_random_child(NULL, "inaccessible", &np);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate inaccessible file node path: %m");
+
+ r = touch_file(np, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0000);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create inaccessible file node '%s': %m", np);
+
+ inaccessible = TAKE_PTR(np);
+ }
+
+ what = inaccessible;
+ } else
+ what = mount_table[k].what;
+
r = path_is_mount_point(where, NULL, 0);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to detect whether %s is a mount point: %m", where);
/* Skip this entry if it is not a remount. */
- if (mount_table[k].what && r > 0)
+ if (what && r > 0)
continue;
r = mkdir_userns_p(dest, where, 0755, mount_settings, uid_shift);
@@ -622,7 +660,7 @@ int mount_all(const char *dest,
}
r = mount_verbose(fatal ? LOG_ERR : LOG_DEBUG,
- mount_table[k].what,
+ what,
where,
mount_table[k].type,
mount_table[k].flags,
@@ -785,11 +823,11 @@ static int mount_overlay(const char *dest, CustomMount *m) {
int mount_custom(
const char *dest,
- CustomMount *mounts, unsigned n,
+ CustomMount *mounts, size_t n,
bool userns, uid_t uid_shift, uid_t uid_range,
const char *selinux_apifs_context) {
- unsigned i;
+ size_t i;
int r;
assert(dest);
@@ -869,8 +907,7 @@ static int get_process_controllers(Set **ret) {
return r;
}
- *ret = controllers;
- controllers = NULL;
+ *ret = TAKE_PTR(controllers);
return 0;
}
diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h
index 79c2390303..b823282cbd 100644
--- a/src/nspawn/nspawn-mount.h
+++ b/src/nspawn/nspawn-mount.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "cgroup-util.h"
@@ -29,9 +10,10 @@ typedef enum MountSettingsMask {
MOUNT_FATAL = 1 << 0, /* if set, a mount error is considered fatal */
MOUNT_USE_USERNS = 1 << 1, /* if set, mounts are patched considering uid/gid shifts in a user namespace */
MOUNT_IN_USERNS = 1 << 2, /* if set, the mount is executed in the inner child, otherwise in the outer child */
- MOUNT_APPLY_APIVFS_RO = 1 << 3, /* if set, /proc/sys, and /sysfs will be mounted read-only, otherwise read-write. */
+ MOUNT_APPLY_APIVFS_RO = 1 << 3, /* if set, /proc/sys, and /sys will be mounted read-only, otherwise read-write. */
MOUNT_APPLY_APIVFS_NETNS = 1 << 4, /* if set, /proc/sys/net will be mounted read-write.
- Works only if MOUNT_APPLY_APIVFS_RO is also set. */
+ Works only if MOUNT_APPLY_APIVFS_RO is also set. */
+ MOUNT_INACCESSIBLE_REG = 1 << 5, /* if set, create an inaccessible regular file first and use as bind mount source */
} MountSettingsMask;
typedef enum CustomMountType {
@@ -53,13 +35,13 @@ typedef struct CustomMount {
char *rm_rf_tmpdir;
} CustomMount;
-CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t);
-void custom_mount_free_all(CustomMount *l, unsigned n);
-int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n);
+CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t);
+void custom_mount_free_all(CustomMount *l, size_t n);
+int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n);
-int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only);
-int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s);
-int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only);
+int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only);
+int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s);
+int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only);
int mount_all(const char *dest, MountSettingsMask mount_settings, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
@@ -67,7 +49,7 @@ int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
int mount_cgroups(const char *dest, CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns);
int mount_systemd_cgroup_writable(const char *dest, CGroupUnified unified_requested);
-int mount_custom(const char *dest, CustomMount *mounts, unsigned n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
+int mount_custom(const char *dest, CustomMount *mounts, size_t n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
int setup_volatile(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
int setup_volatile_state(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c
index ef1da333da..01c57bef56 100644
--- a/src/nspawn/nspawn-network.c
+++ b/src/nspawn/nspawn-network.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/veth.h>
#include <net/if.h>
@@ -338,7 +320,7 @@ static int create_bridge(sd_netlink *rtnl, const char *bridge_name) {
}
int setup_bridge(const char *veth_name, const char *bridge_name, bool create) {
- _cleanup_release_lock_file_ LockFile bridge_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile bridge_lock = LOCK_FILE_INIT;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
int r, bridge_ifi;
unsigned n = 0;
@@ -379,7 +361,7 @@ int setup_bridge(const char *veth_name, const char *bridge_name, bool create) {
}
int remove_bridge(const char *bridge_name) {
- _cleanup_release_lock_file_ LockFile bridge_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile bridge_lock = LOCK_FILE_INIT;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
const char *path;
int r;
@@ -411,7 +393,7 @@ int remove_bridge(const char *bridge_name) {
}
static int parse_interface(struct udev *udev, const char *name) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
char ifi_str[2 + DECIMAL_STR_MAX(int)];
int ifi;
@@ -433,7 +415,7 @@ static int parse_interface(struct udev *udev, const char *name) {
}
int move_network_interfaces(pid_t pid, char **ifaces) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
char **i;
int r;
@@ -476,7 +458,7 @@ int move_network_interfaces(pid_t pid, char **ifaces) {
}
int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
unsigned idx = 0;
char **i;
@@ -564,7 +546,7 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
}
int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
char **i;
int r;
diff --git a/src/nspawn/nspawn-network.h b/src/nspawn/nspawn-network.h
index b79e1397b6..32ea21ccc8 100644
--- a/src/nspawn/nspawn-network.h
+++ b/src/nspawn/nspawn-network.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <net/if.h>
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c
index 7081ed0db2..4a46a25eac 100644
--- a/src/nspawn/nspawn-patch-uid.c
+++ b/src/nspawn/nspawn-patch-uid.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <linux/magic.h>
@@ -175,8 +157,7 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
return -errno;
}
- *ret = copy;
- copy = NULL;
+ *ret = TAKE_PTR(copy);
return !!*ret;
}
diff --git a/src/nspawn/nspawn-patch-uid.h b/src/nspawn/nspawn-patch-uid.h
index fc1d22beb3..31d2491234 100644
--- a/src/nspawn/nspawn-patch-uid.h
+++ b/src/nspawn/nspawn-patch-uid.h
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#pragma once
diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c
index 07d68242c6..93185ecaaa 100644
--- a/src/nspawn/nspawn-register.c
+++ b/src/nspawn/nspawn-register.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-bus.h"
@@ -24,6 +6,7 @@
#include "bus-unit-util.h"
#include "bus-util.h"
#include "nspawn-register.h"
+#include "special.h"
#include "stat-util.h"
#include "strv.h"
#include "util.h"
@@ -32,8 +15,7 @@ static int append_machine_properties(
sd_bus_message *m,
CustomMount *mounts,
unsigned n_mounts,
- int kill_signal,
- char **properties) {
+ int kill_signal) {
unsigned j;
int r;
@@ -198,8 +180,7 @@ int register_machine(
m,
mounts,
n_mounts,
- kill_signal,
- properties);
+ kill_signal);
if (r < 0)
return r;
@@ -293,7 +274,7 @@ int allocate_scope(
if (r < 0)
return log_error_errno(r, "Could not watch job: %m");
- r = unit_name_mangle_with_suffix(machine_name, UNIT_NAME_NOGLOB, ".scope", &scope);
+ r = unit_name_mangle_with_suffix(machine_name, 0, ".scope", &scope);
if (r < 0)
return log_error_errno(r, "Failed to mangle scope name: %m");
@@ -322,7 +303,7 @@ int allocate_scope(
"PIDs", "au", 1, pid,
"Description", "s", description,
"Delegate", "b", 1,
- "Slice", "s", isempty(slice) ? "machine.slice" : slice);
+ "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
if (r < 0)
return bus_log_create_error(r);
@@ -334,8 +315,7 @@ int allocate_scope(
m,
mounts,
n_mounts,
- kill_signal,
- properties);
+ kill_signal);
if (r < 0)
return r;
diff --git a/src/nspawn/nspawn-register.h b/src/nspawn/nspawn-register.h
index fa3644c443..30807b9687 100644
--- a/src/nspawn/nspawn-register.h
+++ b/src/nspawn/nspawn-register.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/types.h>
#include "sd-id128.h"
diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c
index 92e5ff9c36..eb1964bb6d 100644
--- a/src/nspawn/nspawn-seccomp.c
+++ b/src/nspawn/nspawn-seccomp.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <linux/netlink.h>
diff --git a/src/nspawn/nspawn-seccomp.h b/src/nspawn/nspawn-seccomp.h
index 2421b00a12..d852eef638 100644
--- a/src/nspawn/nspawn-seccomp.h
+++ b/src/nspawn/nspawn-seccomp.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/types.h>
int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist);
diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c
index a1518a6e81..62a3486952 100644
--- a/src/nspawn/nspawn-settings.c
+++ b/src/nspawn/nspawn-settings.c
@@ -1,31 +1,17 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "cap-list.h"
#include "conf-parser.h"
+#include "cpu-set-util.h"
+#include "hostname-util.h"
#include "nspawn-network.h"
#include "nspawn-settings.h"
#include "parse-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
@@ -45,8 +31,12 @@ int settings_load(FILE *f, const char *path, Settings **ret) {
s->start_mode = _START_MODE_INVALID;
s->personality = PERSONALITY_INVALID;
s->userns_mode = _USER_NAMESPACE_MODE_INVALID;
+ s->resolv_conf = _RESOLV_CONF_MODE_INVALID;
+ s->link_journal = _LINK_JOURNAL_INVALID;
+ s->timezone = _TIMEZONE_MODE_INVALID;
s->uid_shift = UID_INVALID;
s->uid_range = UID_INVALID;
+ s->no_new_privileges = -1;
s->read_only = -1;
s->volatile_mode = _VOLATILE_MODE_INVALID;
@@ -75,8 +65,7 @@ int settings_load(FILE *f, const char *path, Settings **ret) {
if (s->userns_chown >= 0 && s->userns_mode == _USER_NAMESPACE_MODE_INVALID)
s->userns_mode = USER_NAMESPACE_NO;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
@@ -94,6 +83,9 @@ Settings* settings_free(Settings *s) {
free(s->working_directory);
strv_free(s->syscall_whitelist);
strv_free(s->syscall_blacklist);
+ rlimit_free_all(s->rlimit);
+ free(s->hostname);
+ s->cpuset = cpu_set_mfree(s->cpuset);
strv_free(s->network_interfaces);
strv_free(s->network_macvlan);
@@ -615,3 +607,202 @@ int config_parse_syscall_filter(
return 0;
}
+
+int config_parse_hostname(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char **s = data;
+
+ assert(rvalue);
+ assert(s);
+
+ if (!hostname_is_valid(rvalue, false)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
+ return log_oom();
+
+ return 0;
+}
+
+int config_parse_oom_score_adjust(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Settings *settings = data;
+ int oa, r;
+
+ assert(rvalue);
+ assert(settings);
+
+ if (isempty(rvalue)) {
+ settings->oom_score_adjust_set = false;
+ return 0;
+ }
+
+ r = parse_oom_score_adjust(rvalue, &oa);
+ if (r == -ERANGE) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ settings->oom_score_adjust = oa;
+ settings->oom_score_adjust_set = true;
+
+ return 0;
+}
+
+int config_parse_cpu_affinity(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
+ Settings *settings = data;
+ int ncpus;
+
+ assert(rvalue);
+ assert(settings);
+
+ ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue);
+ if (ncpus < 0)
+ return ncpus;
+
+ if (ncpus == 0) {
+ /* An empty assignment resets the CPU list */
+ settings->cpuset = cpu_set_mfree(settings->cpuset);
+ settings->cpuset_ncpus = 0;
+ return 0;
+ }
+
+ if (!settings->cpuset) {
+ settings->cpuset = TAKE_PTR(cpuset);
+ settings->cpuset_ncpus = (unsigned) ncpus;
+ return 0;
+ }
+
+ if (settings->cpuset_ncpus < (unsigned) ncpus) {
+ CPU_OR_S(CPU_ALLOC_SIZE(settings->cpuset_ncpus), cpuset, settings->cpuset, cpuset);
+ CPU_FREE(settings->cpuset);
+ settings->cpuset = TAKE_PTR(cpuset);
+ settings->cpuset_ncpus = (unsigned) ncpus;
+ return 0;
+ }
+
+ CPU_OR_S(CPU_ALLOC_SIZE((unsigned) ncpus), settings->cpuset, settings->cpuset, cpuset);
+
+ return 0;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_resolv_conf, resolv_conf_mode, ResolvConfMode, "Failed to parse resolv.conf mode");
+
+static const char *const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = {
+ [RESOLV_CONF_OFF] = "off",
+ [RESOLV_CONF_COPY_HOST] = "copy-host",
+ [RESOLV_CONF_COPY_STATIC] = "copy-static",
+ [RESOLV_CONF_BIND_HOST] = "bind-host",
+ [RESOLV_CONF_BIND_STATIC] = "bind-static",
+ [RESOLV_CONF_DELETE] = "delete",
+ [RESOLV_CONF_AUTO] = "auto",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolv_conf_mode, ResolvConfMode, RESOLV_CONF_AUTO);
+
+int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try) {
+ assert(s);
+ assert(ret_mode);
+ assert(ret_try);
+
+ if (streq(s, "auto")) {
+ *ret_mode = LINK_AUTO;
+ *ret_try = false;
+ } else if (streq(s, "no")) {
+ *ret_mode = LINK_NO;
+ *ret_try = false;
+ } else if (streq(s, "guest")) {
+ *ret_mode = LINK_GUEST;
+ *ret_try = false;
+ } else if (streq(s, "host")) {
+ *ret_mode = LINK_HOST;
+ *ret_try = false;
+ } else if (streq(s, "try-guest")) {
+ *ret_mode = LINK_GUEST;
+ *ret_try = true;
+ } else if (streq(s, "try-host")) {
+ *ret_mode = LINK_HOST;
+ *ret_try = true;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+int config_parse_link_journal(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Settings *settings = data;
+ int r;
+
+ assert(rvalue);
+ assert(settings);
+
+ r = parse_link_journal(rvalue, &settings->link_journal, &settings->link_journal_try);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse link journal mode, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ return 0;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_timezone, timezone_mode, TimezoneMode, "Failed to parse timezone mode");
+
+static const char *const timezone_mode_table[_TIMEZONE_MODE_MAX] = {
+ [TIMEZONE_OFF] = "off",
+ [TIMEZONE_COPY] = "copy",
+ [TIMEZONE_BIND] = "bind",
+ [TIMEZONE_SYMLINK] = "symlink",
+ [TIMEZONE_DELETE] = "delete",
+ [TIMEZONE_AUTO] = "auto",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(timezone_mode, TimezoneMode, TIMEZONE_AUTO);
diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h
index 10b8a63052..d522f3cb36 100644
--- a/src/nspawn/nspawn-settings.h
+++ b/src/nspawn/nspawn-settings.h
@@ -1,29 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
+#include <sched.h>
#include <stdio.h>
#include "sd-id128.h"
+#include "conf-parser.h"
#include "macro.h"
#include "nspawn-expose-ports.h"
#include "nspawn-mount.h"
@@ -44,27 +27,78 @@ typedef enum UserNamespaceMode {
_USER_NAMESPACE_MODE_INVALID = -1,
} UserNamespaceMode;
+typedef enum ResolvConfMode {
+ RESOLV_CONF_OFF,
+ RESOLV_CONF_COPY_HOST,
+ RESOLV_CONF_COPY_STATIC,
+ RESOLV_CONF_BIND_HOST,
+ RESOLV_CONF_BIND_STATIC,
+ RESOLV_CONF_DELETE,
+ RESOLV_CONF_AUTO,
+ _RESOLV_CONF_MODE_MAX,
+ _RESOLV_CONF_MODE_INVALID = -1
+} ResolvConfMode;
+
+typedef enum LinkJournal {
+ LINK_NO,
+ LINK_AUTO,
+ LINK_HOST,
+ LINK_GUEST,
+ _LINK_JOURNAL_MAX,
+ _LINK_JOURNAL_INVALID = -1
+} LinkJournal;
+
+typedef enum TimezoneMode {
+ TIMEZONE_OFF,
+ TIMEZONE_COPY,
+ TIMEZONE_BIND,
+ TIMEZONE_SYMLINK,
+ TIMEZONE_DELETE,
+ TIMEZONE_AUTO,
+ _TIMEZONE_MODE_MAX,
+ _TIMEZONE_MODE_INVALID = -1
+} TimezoneMode;
+
typedef enum SettingsMask {
- SETTING_START_MODE = 1 << 0,
- SETTING_ENVIRONMENT = 1 << 1,
- SETTING_USER = 1 << 2,
- SETTING_CAPABILITY = 1 << 3,
- SETTING_KILL_SIGNAL = 1 << 4,
- SETTING_PERSONALITY = 1 << 5,
- SETTING_MACHINE_ID = 1 << 6,
- SETTING_NETWORK = 1 << 7,
- SETTING_EXPOSE_PORTS = 1 << 8,
- SETTING_READ_ONLY = 1 << 9,
- SETTING_VOLATILE_MODE = 1 << 10,
- SETTING_CUSTOM_MOUNTS = 1 << 11,
- SETTING_WORKING_DIRECTORY = 1 << 12,
- SETTING_USERNS = 1 << 13,
- SETTING_NOTIFY_READY = 1 << 14,
- SETTING_PIVOT_ROOT = 1 << 15,
- SETTING_SYSCALL_FILTER = 1 << 16,
- _SETTINGS_MASK_ALL = (1 << 17) -1
+ SETTING_START_MODE = UINT64_C(1) << 0,
+ SETTING_ENVIRONMENT = UINT64_C(1) << 1,
+ SETTING_USER = UINT64_C(1) << 2,
+ SETTING_CAPABILITY = UINT64_C(1) << 3,
+ SETTING_KILL_SIGNAL = UINT64_C(1) << 4,
+ SETTING_PERSONALITY = UINT64_C(1) << 5,
+ SETTING_MACHINE_ID = UINT64_C(1) << 6,
+ SETTING_NETWORK = UINT64_C(1) << 7,
+ SETTING_EXPOSE_PORTS = UINT64_C(1) << 8,
+ SETTING_READ_ONLY = UINT64_C(1) << 9,
+ SETTING_VOLATILE_MODE = UINT64_C(1) << 10,
+ SETTING_CUSTOM_MOUNTS = UINT64_C(1) << 11,
+ SETTING_WORKING_DIRECTORY = UINT64_C(1) << 12,
+ SETTING_USERNS = UINT64_C(1) << 13,
+ SETTING_NOTIFY_READY = UINT64_C(1) << 14,
+ SETTING_PIVOT_ROOT = UINT64_C(1) << 15,
+ SETTING_SYSCALL_FILTER = UINT64_C(1) << 16,
+ SETTING_HOSTNAME = UINT64_C(1) << 17,
+ SETTING_NO_NEW_PRIVILEGES = UINT64_C(1) << 18,
+ SETTING_OOM_SCORE_ADJUST = UINT64_C(1) << 19,
+ SETTING_CPU_AFFINITY = UINT64_C(1) << 20,
+ SETTING_RESOLV_CONF = UINT64_C(1) << 21,
+ SETTING_LINK_JOURNAL = UINT64_C(1) << 22,
+ SETTING_TIMEZONE = UINT64_C(1) << 23,
+ SETTING_RLIMIT_FIRST = UINT64_C(1) << 24, /* we define one bit per resource limit here */
+ SETTING_RLIMIT_LAST = UINT64_C(1) << (24 + _RLIMIT_MAX - 1),
+ _SETTINGS_MASK_ALL = (UINT64_C(1) << (24 + _RLIMIT_MAX)) -1,
+ _SETTING_FORCE_ENUM_WIDTH = UINT64_MAX
} SettingsMask;
+/* We want to use SETTING_RLIMIT_FIRST in shifts, so make sure it is really 64 bits
+ * when used in expressions. */
+#define SETTING_RLIMIT_FIRST ((uint64_t) SETTING_RLIMIT_FIRST)
+#define SETTING_RLIMIT_LAST ((uint64_t) SETTING_RLIMIT_LAST)
+
+assert_cc(sizeof(SettingsMask) == 8);
+assert_cc(sizeof(SETTING_RLIMIT_FIRST) == 8);
+assert_cc(sizeof(SETTING_RLIMIT_LAST) == 8);
+
typedef struct Settings {
/* [Run] */
StartMode start_mode;
@@ -84,12 +118,23 @@ typedef struct Settings {
bool notify_ready;
char **syscall_whitelist;
char **syscall_blacklist;
+ struct rlimit *rlimit[_RLIMIT_MAX];
+ char *hostname;
+ int no_new_privileges;
+ int oom_score_adjust;
+ bool oom_score_adjust_set;
+ cpu_set_t *cpuset;
+ unsigned cpuset_ncpus;
+ ResolvConfMode resolv_conf;
+ LinkJournal link_journal;
+ bool link_journal_try;
+ TimezoneMode timezone;
/* [Image] */
int read_only;
VolatileMode volatile_mode;
CustomMount *custom_mounts;
- unsigned n_custom_mounts;
+ size_t n_custom_mounts;
int userns_chown;
/* [Network] */
@@ -114,17 +159,31 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Settings*, settings_free);
const struct ConfigPerfItem* nspawn_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-int config_parse_capability(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_id128(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_expose_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_volatile_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_pivot_root(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tmpfs(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_overlay(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_veth_extra(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_network_zone(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_boot(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_pid2(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_private_users(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_filter(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_capability);
+CONFIG_PARSER_PROTOTYPE(config_parse_id128);
+CONFIG_PARSER_PROTOTYPE(config_parse_expose_port);
+CONFIG_PARSER_PROTOTYPE(config_parse_volatile_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_pivot_root);
+CONFIG_PARSER_PROTOTYPE(config_parse_bind);
+CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs);
+CONFIG_PARSER_PROTOTYPE(config_parse_overlay);
+CONFIG_PARSER_PROTOTYPE(config_parse_veth_extra);
+CONFIG_PARSER_PROTOTYPE(config_parse_network_zone);
+CONFIG_PARSER_PROTOTYPE(config_parse_boot);
+CONFIG_PARSER_PROTOTYPE(config_parse_pid2);
+CONFIG_PARSER_PROTOTYPE(config_parse_private_users);
+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
+CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
+CONFIG_PARSER_PROTOTYPE(config_parse_oom_score_adjust);
+CONFIG_PARSER_PROTOTYPE(config_parse_cpu_affinity);
+CONFIG_PARSER_PROTOTYPE(config_parse_resolv_conf);
+CONFIG_PARSER_PROTOTYPE(config_parse_link_journal);
+CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
+
+const char *resolv_conf_mode_to_string(ResolvConfMode a) _const_;
+ResolvConfMode resolv_conf_mode_from_string(const char *s) _pure_;
+
+const char *timezone_mode_to_string(TimezoneMode a) _const_;
+TimezoneMode timezone_mode_from_string(const char *s) _pure_;
+
+int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try);
diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c
index 2dee5f8ec8..44f5b17675 100644
--- a/src/nspawn/nspawn-setuid.c
+++ b/src/nspawn/nspawn-setuid.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <grp.h>
#include <sys/types.h>
@@ -226,8 +208,8 @@ int change_uid_gid(const char *user, char **_home) {
if (r < 0)
return log_error_errno(r, "Failed to make home root directory: %m");
- r = mkdir_safe(home, 0755, uid, gid, false);
- if (r < 0 && r != -EEXIST)
+ r = mkdir_safe(home, 0755, uid, gid, 0);
+ if (r < 0 && !IN_SET(r, -EEXIST, -ENOTDIR))
return log_error_errno(r, "Failed to make home directory: %m");
(void) fchown(STDIN_FILENO, uid, gid);
@@ -243,10 +225,8 @@ int change_uid_gid(const char *user, char **_home) {
if (setresuid(uid, uid, uid) < 0)
return log_error_errno(errno, "setresuid() failed: %m");
- if (_home) {
- *_home = home;
- home = NULL;
- }
+ if (_home)
+ *_home = TAKE_PTR(home);
return 0;
}
diff --git a/src/nspawn/nspawn-setuid.h b/src/nspawn/nspawn-setuid.h
index 20fc8854f1..0ae47cb6b3 100644
--- a/src/nspawn/nspawn-setuid.h
+++ b/src/nspawn/nspawn-setuid.h
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int change_uid_gid(const char *user, char **ret);
diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c
index 58f4636866..c83d55cb86 100644
--- a/src/nspawn/nspawn-stub-pid1.c
+++ b/src/nspawn/nspawn-stub-pid1.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/reboot.h>
#include <sys/wait.h>
diff --git a/src/nspawn/nspawn-stub-pid1.h b/src/nspawn/nspawn-stub-pid1.h
index fef2252e22..8982d5034e 100644
--- a/src/nspawn/nspawn-stub-pid1.h
+++ b/src/nspawn/nspawn-stub-pid1.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-id128.h"
int stub_pid1(sd_id128_t uuid);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 8959fd3172..56877bd932 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#if HAVE_BLKID
#include <blkid.h>
@@ -51,11 +33,13 @@
#include "base-filesystem.h"
#include "blkid-util.h"
#include "btrfs-util.h"
+#include "bus-error.h"
#include "bus-util.h"
#include "cap-list.h"
#include "capability-util.h"
#include "cgroup-util.h"
#include "copy.h"
+#include "cpu-set-util.h"
#include "dev-setup.h"
#include "dissect-image.h"
#include "env-util.h"
@@ -88,18 +72,22 @@
#include "nspawn-settings.h"
#include "nspawn-setuid.h"
#include "nspawn-stub-pid1.h"
+#include "os-util.h"
+#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "ptyfwd.h"
#include "random-util.h"
#include "raw-clone.h"
+#include "rlimit-util.h"
#include "rm-rf.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "stat-util.h"
#include "stdio-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
@@ -126,13 +114,6 @@ typedef enum ContainerStatus {
CONTAINER_REBOOTED
} ContainerStatus;
-typedef enum LinkJournal {
- LINK_NO,
- LINK_AUTO,
- LINK_HOST,
- LINK_GUEST
-} LinkJournal;
-
static char *arg_directory = NULL;
static char *arg_template = NULL;
static char *arg_chdir = NULL;
@@ -140,7 +121,8 @@ static char *arg_pivot_root_new = NULL;
static char *arg_pivot_root_old = NULL;
static char *arg_user = NULL;
static sd_id128_t arg_uuid = {};
-static char *arg_machine = NULL;
+static char *arg_machine = NULL; /* The name used by the host to refer to this */
+static char *arg_hostname = NULL; /* The name the payload sees by default */
static const char *arg_selinux_context = NULL;
static const char *arg_selinux_apifs_context = NULL;
static const char *arg_slice = NULL;
@@ -178,7 +160,7 @@ static uint64_t arg_caps_retain =
(1ULL << CAP_SYS_RESOURCE) |
(1ULL << CAP_SYS_TTY_CONFIG);
static CustomMount *arg_custom_mounts = NULL;
-static unsigned arg_n_custom_mounts = 0;
+static size_t arg_n_custom_mounts = 0;
static char **arg_setenv = NULL;
static bool arg_quiet = false;
static bool arg_register = true;
@@ -213,8 +195,18 @@ static void *arg_root_hash = NULL;
static size_t arg_root_hash_size = 0;
static char **arg_syscall_whitelist = NULL;
static char **arg_syscall_blacklist = NULL;
+static struct rlimit *arg_rlimit[_RLIMIT_MAX] = {};
+static bool arg_no_new_privileges = false;
+static int arg_oom_score_adjust = 0;
+static bool arg_oom_score_adjust_set = false;
+static cpu_set_t *arg_cpuset = NULL;
+static unsigned arg_cpuset_ncpus = 0;
+static ResolvConfMode arg_resolv_conf = RESOLV_CONF_AUTO;
+static TimezoneMode arg_timezone = TIMEZONE_AUTO;
static void help(void) {
+ (void) pager_open(false, false);
+
printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
"Spawn a minimal namespace container for debugging, testing and building.\n\n"
" -h --help Show this help\n"
@@ -234,6 +226,7 @@ static void help(void) {
" Pivot root to given directory in the container\n"
" -u --user=USER Run the command under specified user or uid\n"
" -M --machine=NAME Set the machine name for the container\n"
+ " --hostname=NAME Override the hostname for the container\n"
" --uuid=UUID Set a specific machine UUID for the container\n"
" -S --slice=SLICE Place the container in the specified slice\n"
" --property=NAME=VALUE Set scope unit property\n"
@@ -277,10 +270,16 @@ static void help(void) {
" --drop-capability=CAP Drop the specified capability from the default set\n"
" --system-call-filter=LIST|~LIST\n"
" Permit/prohibit specific system calls\n"
+ " --rlimit=NAME=LIMIT Set a resource limit for the payload\n"
+ " --oom-score-adjust=VALUE\n"
+ " Adjust the OOM score value for the payload\n"
+ " --cpu-affinity=CPUS Adjust the CPU affinity of the container\n"
" --kill-signal=SIGNAL Select signal to use for shutting down PID 1\n"
" --link-journal=MODE Link up guest journal, one of no, auto, guest, \n"
" host, try-guest, try-host\n"
" -j Equivalent to --link-journal=try-guest\n"
+ " --resolv-conf=MODE Select mode of /etc/resolv.conf initialization\n"
+ " --timezone=MODE Select mode of /etc/localtime initialization\n"
" --read-only Mount the root directory read-only\n"
" --bind=PATH[:PATH[:OPTIONS]]\n"
" Bind mount a file or directory from the host into\n"
@@ -304,7 +303,7 @@ static void help(void) {
}
static int custom_mount_check_all(void) {
- unsigned i;
+ size_t i;
for (i = 0; i < arg_n_custom_mounts; i++) {
CustomMount *m = &arg_custom_mounts[i];
@@ -415,7 +414,6 @@ static void parse_mount_settings_env(void) {
}
static int parse_argv(int argc, char *argv[]) {
-
enum {
ARG_VERSION = 0x100,
ARG_PRIVATE_NETWORK,
@@ -452,6 +450,13 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NOTIFY_READY,
ARG_ROOT_HASH,
ARG_SYSTEM_CALL_FILTER,
+ ARG_RLIMIT,
+ ARG_HOSTNAME,
+ ARG_NO_NEW_PRIVILEGES,
+ ARG_OOM_SCORE_ADJUST,
+ ARG_CPU_AFFINITY,
+ ARG_RESOLV_CONF,
+ ARG_TIMEZONE,
};
static const struct option options[] = {
@@ -468,6 +473,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
{ "capability", required_argument, NULL, ARG_CAPABILITY },
{ "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY },
+ { "no-new-privileges", required_argument, NULL, ARG_NO_NEW_PRIVILEGES },
{ "link-journal", required_argument, NULL, ARG_LINK_JOURNAL },
{ "bind", required_argument, NULL, ARG_BIND },
{ "bind-ro", required_argument, NULL, ARG_BIND_RO },
@@ -475,6 +481,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "overlay", required_argument, NULL, ARG_OVERLAY },
{ "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO },
{ "machine", required_argument, NULL, 'M' },
+ { "hostname", required_argument, NULL, ARG_HOSTNAME },
{ "slice", required_argument, NULL, 'S' },
{ "setenv", required_argument, NULL, 'E' },
{ "selinux-context", required_argument, NULL, 'Z' },
@@ -505,6 +512,11 @@ static int parse_argv(int argc, char *argv[]) {
{ "notify-ready", required_argument, NULL, ARG_NOTIFY_READY },
{ "root-hash", required_argument, NULL, ARG_ROOT_HASH },
{ "system-call-filter", required_argument, NULL, ARG_SYSTEM_CALL_FILTER },
+ { "rlimit", required_argument, NULL, ARG_RLIMIT },
+ { "oom-score-adjust", required_argument, NULL, ARG_OOM_SCORE_ADJUST },
+ { "cpu-affinity", required_argument, NULL, ARG_CPU_AFFINITY },
+ { "resolv-conf", required_argument, NULL, ARG_RESOLV_CONF },
+ { "timezone", required_argument, NULL, ARG_TIMEZONE },
{}
};
@@ -517,7 +529,6 @@ static int parse_argv(int argc, char *argv[]) {
assert(argv);
while ((c = getopt_long(argc, argv, "+hD:u:abL:M:jS:Z:qi:xp:nUE:", options, NULL)) >= 0)
-
switch (c) {
case 'h':
@@ -570,8 +581,7 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- free(arg_network_zone);
- arg_network_zone = j;
+ free_and_replace(arg_network_zone, j);
arg_network_veth = true;
arg_private_network = true;
@@ -607,7 +617,6 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_NETWORK_INTERFACE:
-
if (!ifname_valid(optarg)) {
log_error("Network interface name not valid: %s", optarg);
return -EINVAL;
@@ -709,6 +718,23 @@ static int parse_argv(int argc, char *argv[]) {
}
break;
+ case ARG_HOSTNAME:
+ if (isempty(optarg))
+ arg_hostname = mfree(arg_hostname);
+ else {
+ if (!hostname_is_valid(optarg, false)) {
+ log_error("Invalid hostname: %s", optarg);
+ return -EINVAL;
+ }
+
+ r = free_and_strdup(&arg_hostname, optarg);
+ if (r < 0)
+ return log_oom();
+ }
+
+ arg_settings_mask |= SETTING_HOSTNAME;
+ break;
+
case 'Z':
arg_selinux_context = optarg;
break;
@@ -760,35 +786,29 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
+ case ARG_NO_NEW_PRIVILEGES:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --no-new-privileges= argument: %s", optarg);
+
+ arg_no_new_privileges = r;
+ arg_settings_mask |= SETTING_NO_NEW_PRIVILEGES;
+ break;
+
case 'j':
arg_link_journal = LINK_GUEST;
arg_link_journal_try = true;
+ arg_settings_mask |= SETTING_LINK_JOURNAL;
break;
case ARG_LINK_JOURNAL:
- if (streq(optarg, "auto")) {
- arg_link_journal = LINK_AUTO;
- arg_link_journal_try = false;
- } else if (streq(optarg, "no")) {
- arg_link_journal = LINK_NO;
- arg_link_journal_try = false;
- } else if (streq(optarg, "guest")) {
- arg_link_journal = LINK_GUEST;
- arg_link_journal_try = false;
- } else if (streq(optarg, "host")) {
- arg_link_journal = LINK_HOST;
- arg_link_journal_try = false;
- } else if (streq(optarg, "try-guest")) {
- arg_link_journal = LINK_GUEST;
- arg_link_journal_try = true;
- } else if (streq(optarg, "try-host")) {
- arg_link_journal = LINK_HOST;
- arg_link_journal_try = true;
- } else {
- log_error("Failed to parse link journal mode %s", optarg);
+ r = parse_link_journal(optarg, &arg_link_journal, &arg_link_journal_try);
+ if (r < 0) {
+ log_error_errno(r, "Failed to parse link journal mode %s", optarg);
return -EINVAL;
}
+ arg_settings_mask |= SETTING_LINK_JOURNAL;
break;
case ARG_BIND:
@@ -831,9 +851,7 @@ static int parse_argv(int argc, char *argv[]) {
if (!n)
return log_oom();
- strv_free(arg_setenv);
- arg_setenv = n;
-
+ strv_free_and_replace(arg_setenv, n);
arg_settings_mask |= SETTING_ENVIRONMENT;
break;
}
@@ -845,6 +863,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_SHARE_SYSTEM:
/* We don't officially support this anymore, except for compat reasons. People should use the
* $SYSTEMD_NSPAWN_SHARE_* environment variables instead. */
+ log_warning("Please do not use --share-system anymore, use $SYSTEMD_NSPAWN_SHARE_* instead.");
arg_clone_ns_flags = 0;
break;
@@ -877,7 +896,10 @@ static int parse_argv(int argc, char *argv[]) {
if (!optarg)
arg_volatile_mode = VOLATILE_YES;
- else {
+ else if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(volatile_mode, VolatileMode, _VOLATILE_MODE_MAX);
+ return 0;
+ } else {
VolatileMode m;
m = volatile_mode_from_string(optarg);
@@ -985,7 +1007,12 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_KILL_SIGNAL:
- arg_kill_signal = signal_from_string_try_harder(optarg);
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
+ arg_kill_signal = signal_from_string(optarg);
if (arg_kill_signal < 0) {
log_error("Cannot parse signal: %s", optarg);
return -EINVAL;
@@ -1109,6 +1136,101 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
+ case ARG_RLIMIT: {
+ const char *eq;
+ char *name;
+ int rl;
+
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(rlimit, int, _RLIMIT_MAX);
+ return 0;
+ }
+
+ eq = strchr(optarg, '=');
+ if (!eq) {
+ log_error("--rlimit= expects an '=' assignment.");
+ return -EINVAL;
+ }
+
+ name = strndup(optarg, eq - optarg);
+ if (!name)
+ return log_oom();
+
+ rl = rlimit_from_string_harder(name);
+ if (rl < 0) {
+ log_error("Unknown resource limit: %s", name);
+ return -EINVAL;
+ }
+
+ if (!arg_rlimit[rl]) {
+ arg_rlimit[rl] = new0(struct rlimit, 1);
+ if (!arg_rlimit[rl])
+ return log_oom();
+ }
+
+ r = rlimit_parse(rl, eq + 1, arg_rlimit[rl]);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse resource limit: %s", eq + 1);
+
+ arg_settings_mask |= SETTING_RLIMIT_FIRST << rl;
+ break;
+ }
+
+ case ARG_OOM_SCORE_ADJUST:
+ r = parse_oom_score_adjust(optarg, &arg_oom_score_adjust);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --oom-score-adjust= parameter: %s", optarg);
+
+ arg_oom_score_adjust_set = true;
+ arg_settings_mask |= SETTING_OOM_SCORE_ADJUST;
+ break;
+
+ case ARG_CPU_AFFINITY: {
+ _cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
+
+ r = parse_cpu_set(optarg, &cpuset);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse CPU affinity mask: %s", optarg);
+
+ if (arg_cpuset)
+ CPU_FREE(arg_cpuset);
+
+ arg_cpuset = TAKE_PTR(cpuset);
+ arg_cpuset_ncpus = r;
+ arg_settings_mask |= SETTING_CPU_AFFINITY;
+ break;
+ }
+
+ case ARG_RESOLV_CONF:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(resolv_conf_mode, ResolvConfMode, _RESOLV_CONF_MODE_MAX);
+ return 0;
+ }
+
+ arg_resolv_conf = resolv_conf_mode_from_string(optarg);
+ if (arg_resolv_conf < 0) {
+ log_error("Failed to parse /etc/resolv.conf mode: %s", optarg);
+ return -EINVAL;
+ }
+
+ arg_settings_mask |= SETTING_RESOLV_CONF;
+ break;
+
+ case ARG_TIMEZONE:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(timezone_mode, TimezoneMode, _TIMEZONE_MODE_MAX);
+ return 0;
+ }
+
+ arg_timezone = timezone_mode_from_string(optarg);
+ if (arg_timezone < 0) {
+ log_error("Failed to parse /etc/localtime mode: %s", optarg);
+ return -EINVAL;
+ }
+
+ arg_settings_mask |= SETTING_TIMEZONE;
+ break;
+
case '?':
return -EINVAL;
@@ -1175,8 +1297,7 @@ static int parse_argv(int argc, char *argv[]) {
* accept this here, and silently make "--ephemeral --template=" equivalent to "--ephemeral
* --directory=". */
- arg_directory = arg_template;
- arg_template = NULL;
+ arg_directory = TAKE_PTR(arg_template);
}
if (arg_template && !(arg_directory || arg_machine)) {
@@ -1325,77 +1446,165 @@ static int userns_mkdir(const char *root, const char *path, mode_t mode, uid_t u
return userns_lchown(q, uid, gid);
}
+static const char *timezone_from_path(const char *path) {
+ const char *z;
+
+ z = path_startswith(path, "../usr/share/zoneinfo/");
+ if (z)
+ return z;
+
+ z = path_startswith(path, "/usr/share/zoneinfo/");
+ if (z)
+ return z;
+
+ return NULL;
+}
+
static int setup_timezone(const char *dest) {
- _cleanup_free_ char *p = NULL, *q = NULL;
- const char *where, *check, *what;
- char *z, *y;
+ _cleanup_free_ char *p = NULL, *etc = NULL;
+ const char *where, *check;
+ TimezoneMode m;
int r;
assert(dest);
- /* Fix the timezone, if possible */
- r = readlink_malloc("/etc/localtime", &p);
+ if (IN_SET(arg_timezone, TIMEZONE_AUTO, TIMEZONE_SYMLINK)) {
+ r = readlink_malloc("/etc/localtime", &p);
+ if (r == -ENOENT && arg_timezone == TIMEZONE_AUTO)
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? TIMEZONE_OFF : TIMEZONE_DELETE;
+ else if (r == -EINVAL && arg_timezone == TIMEZONE_AUTO) /* regular file? */
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? TIMEZONE_BIND : TIMEZONE_COPY;
+ else if (r < 0) {
+ log_warning_errno(r, "Failed to read host's /etc/localtime symlink, not updating container timezone: %m");
+ /* To handle warning, delete /etc/localtime and replace it with a symbolic link to a time zone data
+ * file.
+ *
+ * Example:
+ * ln -s /usr/share/zoneinfo/UTC /etc/localtime
+ */
+ return 0;
+ } else if (arg_timezone == TIMEZONE_AUTO)
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? TIMEZONE_BIND : TIMEZONE_SYMLINK;
+ else
+ m = arg_timezone;
+ } else
+ m = arg_timezone;
+
+ if (m == TIMEZONE_OFF)
+ return 0;
+
+ r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
if (r < 0) {
- log_warning("host's /etc/localtime is not a symlink, not updating container timezone.");
- /* to handle warning, delete /etc/localtime and replace it
- * with a symbolic link to a time zone data file.
- *
- * Example:
- * ln -s /usr/share/zoneinfo/UTC /etc/localtime
- */
+ log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m");
return 0;
}
- z = path_startswith(p, "../usr/share/zoneinfo/");
- if (!z)
- z = path_startswith(p, "/usr/share/zoneinfo/");
- if (!z) {
- log_warning("/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone.");
+ where = strjoina(etc, "/localtime");
+
+ switch (m) {
+
+ case TIMEZONE_DELETE:
+ if (unlink(where) < 0)
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to remove '%s', ignoring: %m", where);
+
return 0;
- }
- where = prefix_roota(dest, "/etc/localtime");
- r = readlink_malloc(where, &q);
- if (r >= 0) {
- y = path_startswith(q, "../usr/share/zoneinfo/");
- if (!y)
- y = path_startswith(q, "/usr/share/zoneinfo/");
+ case TIMEZONE_SYMLINK: {
+ _cleanup_free_ char *q = NULL;
+ const char *z, *what;
- /* Already pointing to the right place? Then do nothing .. */
- if (y && streq(y, z))
+ z = timezone_from_path(p);
+ if (!z) {
+ log_warning("/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone.");
return 0;
- }
+ }
- check = strjoina("/usr/share/zoneinfo/", z);
- check = prefix_roota(dest, check);
- if (laccess(check, F_OK) < 0) {
- log_warning("Timezone %s does not exist in container, not updating container timezone.", z);
- return 0;
+ r = readlink_malloc(where, &q);
+ if (r >= 0 && streq_ptr(timezone_from_path(q), z))
+ return 0; /* Already pointing to the right place? Then do nothing .. */
+
+ check = strjoina(dest, "/usr/share/zoneinfo/", z);
+ r = chase_symlinks(check, dest, 0, NULL);
+ if (r < 0)
+ log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z);
+ else {
+ if (unlink(where) < 0 && errno != ENOENT) {
+ log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, /* Don't complain on read-only images */
+ errno, "Failed to remove existing timezone info %s in container, ignoring: %m", where);
+ return 0;
+ }
+
+ what = strjoina("../usr/share/zoneinfo/", z);
+ if (symlink(what, where) < 0) {
+ log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING,
+ errno, "Failed to correct timezone of container, ignoring: %m");
+ return 0;
+ }
+
+ break;
+ }
+
+ _fallthrough_;
}
- if (unlink(where) < 0 && errno != ENOENT) {
- log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, /* Don't complain on read-only images */
- errno,
- "Failed to remove existing timezone info %s in container, ignoring: %m", where);
- return 0;
+ case TIMEZONE_BIND: {
+ _cleanup_free_ char *resolved = NULL;
+ int found;
+
+ found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
+ if (found < 0) {
+ log_warning_errno(found, "Failed to resolve /etc/localtime path in container, ignoring: %m");
+ return 0;
+ }
+
+ if (found == 0) /* missing? */
+ (void) touch(resolved);
+
+ r = mount_verbose(LOG_WARNING, "/etc/localtime", resolved, NULL, MS_BIND, NULL);
+ if (r >= 0)
+ return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL);
+
+ _fallthrough_;
}
- what = strjoina("../usr/share/zoneinfo/", z);
- if (symlink(what, where) < 0) {
- log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING,
- errno,
- "Failed to correct timezone of container, ignoring: %m");
- return 0;
+ case TIMEZONE_COPY:
+ /* If mounting failed, try to copy */
+ r = copy_file_atomic("/etc/localtime", where, 0644, 0, COPY_REFLINK|COPY_REPLACE);
+ if (r < 0) {
+ log_full_errno(IN_SET(r, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to copy /etc/localtime to %s, ignoring: %m", where);
+ return 0;
+ }
+
+ break;
+
+ default:
+ assert_not_reached("unexpected mode");
}
+ /* Fix permissions of the symlink or file copy we just created */
r = userns_lchown(where, 0, 0);
if (r < 0)
- return log_warning_errno(r, "Failed to chown /etc/localtime: %m");
+ log_warning_errno(r, "Failed to chown /etc/localtime, ignoring: %m");
return 0;
}
+static int have_resolv_conf(const char *path) {
+ assert(path);
+
+ if (access(path, F_OK) < 0) {
+ if (errno == ENOENT)
+ return 0;
+
+ return log_debug_errno(errno, "Failed to determine whether '%s' is available: %m", path);
+ }
+
+ return 1;
+}
+
static int resolved_listening(void) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ char *dns_stub_listener_mode = NULL;
int r;
@@ -1404,33 +1613,53 @@ static int resolved_listening(void) {
r = sd_bus_open_system(&bus);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to open system bus: %m");
r = bus_name_has_owner(bus, "org.freedesktop.resolve1", NULL);
- if (r <= 0)
- return r;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to check whether the 'org.freedesktop.resolve1' bus name is taken: %m");
+ if (r == 0)
+ return 0;
r = sd_bus_get_property_string(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"DNSStubListener",
- NULL,
+ &error,
&dns_stub_listener_mode);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to query DNSStubListener property: %s", bus_error_message(&error, r));
return STR_IN_SET(dns_stub_listener_mode, "udp", "yes");
}
static int setup_resolv_conf(const char *dest) {
- _cleanup_free_ char *resolved = NULL, *etc = NULL;
- const char *where;
- int r, found;
+ _cleanup_free_ char *etc = NULL;
+ const char *where, *what;
+ ResolvConfMode m;
+ int r;
assert(dest);
- if (arg_private_network)
+ if (arg_resolv_conf == RESOLV_CONF_AUTO) {
+ if (arg_private_network)
+ m = RESOLV_CONF_OFF;
+ else if (have_resolv_conf(STATIC_RESOLV_CONF) > 0 && resolved_listening() > 0)
+ /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the
+ * container, so that the container can use the host's resolver. Given that network namespacing is
+ * disabled it's only natural of the container also uses the host's resolver. It also has the big
+ * advantage that the container will be able to follow the host's DNS server configuration changes
+ * transparently. */
+ m = RESOLV_CONF_BIND_STATIC;
+ else if (have_resolv_conf("/etc/resolv.conf") > 0)
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? RESOLV_CONF_BIND_HOST : RESOLV_CONF_COPY_HOST;
+ else
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? RESOLV_CONF_OFF : RESOLV_CONF_DELETE;
+ } else
+ m = arg_resolv_conf;
+
+ if (m == RESOLV_CONF_OFF)
return 0;
r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
@@ -1440,38 +1669,46 @@ static int setup_resolv_conf(const char *dest) {
}
where = strjoina(etc, "/resolv.conf");
- found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
- if (found < 0) {
- log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m");
+
+ if (m == RESOLV_CONF_DELETE) {
+ if (unlink(where) < 0)
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to remove '%s', ignoring: %m", where);
+
return 0;
}
- if (access(STATIC_RESOLV_CONF, F_OK) >= 0 &&
- resolved_listening() > 0) {
+ if (IN_SET(m, RESOLV_CONF_BIND_STATIC, RESOLV_CONF_COPY_STATIC))
+ what = STATIC_RESOLV_CONF;
+ else
+ what = "/etc/resolv.conf";
- /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the
- * container, so that the container can use the host's resolver. Given that network namespacing is
- * disabled it's only natural of the container also uses the host's resolver. It also has the big
- * advantage that the container will be able to follow the host's DNS server configuration changes
- * transparently. */
+ if (IN_SET(m, RESOLV_CONF_BIND_HOST, RESOLV_CONF_BIND_STATIC)) {
+ _cleanup_free_ char *resolved = NULL;
+ int found;
+
+ found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
+ if (found < 0) {
+ log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m");
+ return 0;
+ }
if (found == 0) /* missing? */
(void) touch(resolved);
- r = mount_verbose(LOG_DEBUG, STATIC_RESOLV_CONF, resolved, NULL, MS_BIND, NULL);
+ r = mount_verbose(LOG_WARNING, what, resolved, NULL, MS_BIND, NULL);
if (r >= 0)
return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL);
}
/* If that didn't work, let's copy the file */
- r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644, 0, COPY_REFLINK);
+ r = copy_file(what, where, O_TRUNC|O_NOFOLLOW, 0644, 0, COPY_REFLINK);
if (r < 0) {
/* If the file already exists as symlink, let's suppress the warning, under the assumption that
* resolved or something similar runs inside and the symlink points there.
*
* If the disk image is read-only, there's also no point in complaining.
*/
- log_full_errno(IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(!IN_SET(RESOLV_CONF_COPY_HOST, RESOLV_CONF_COPY_STATIC) && IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to copy /etc/resolv.conf to %s, ignoring: %m", where);
return 0;
}
@@ -1483,36 +1720,39 @@ static int setup_resolv_conf(const char *dest) {
return 0;
}
-static int setup_boot_id(const char *dest) {
+static int setup_boot_id(void) {
+ _cleanup_(unlink_and_freep) char *from = NULL;
+ _cleanup_free_ char *path = NULL;
sd_id128_t rnd = SD_ID128_NULL;
- const char *from, *to;
+ const char *to;
int r;
/* Generate a new randomized boot ID, so that each boot-up of
* the container gets a new one */
- from = prefix_roota(dest, "/run/proc-sys-kernel-random-boot-id");
- to = prefix_roota(dest, "/proc/sys/kernel/random/boot_id");
+ r = tempfn_random_child(NULL, "proc-sys-kernel-random-boot-id", &path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate random boot ID path: %m");
r = sd_id128_randomize(&rnd);
if (r < 0)
return log_error_errno(r, "Failed to generate random boot id: %m");
- r = id128_write(from, ID128_UUID, rnd, false);
+ r = id128_write(path, ID128_UUID, rnd, false);
if (r < 0)
return log_error_errno(r, "Failed to write boot id: %m");
+ from = TAKE_PTR(path);
+ to = "/proc/sys/kernel/random/boot_id";
+
r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL);
- if (r >= 0)
- r = mount_verbose(LOG_ERR, NULL, to, NULL,
- MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL);
+ if (r < 0)
+ return r;
- (void) unlink(from);
- return r;
+ return mount_verbose(LOG_ERR, NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
}
static int copy_devnodes(const char *dest) {
-
static const char devnodes[] =
"null\0"
"zero\0"
@@ -1675,46 +1915,46 @@ static int setup_keyring(void) {
return 0;
}
-static int setup_kmsg(const char *dest, int kmsg_socket) {
- const char *from, *to;
+static int setup_kmsg(int kmsg_socket) {
+ _cleanup_(unlink_and_freep) char *from = NULL;
+ _cleanup_free_ char *fifo = NULL;
+ _cleanup_close_ int fd = -1;
_cleanup_umask_ mode_t u;
- int fd, r;
+ const char *to;
+ int r;
assert(kmsg_socket >= 0);
u = umask(0000);
- /* We create the kmsg FIFO as /run/kmsg, but immediately
- * delete it after bind mounting it to /proc/kmsg. While FIFOs
- * on the reading side behave very similar to /proc/kmsg,
- * their writing side behaves differently from /dev/kmsg in
- * that writing blocks when nothing is reading. In order to
- * avoid any problems with containers deadlocking due to this
- * we simply make /dev/kmsg unavailable to the container. */
- from = prefix_roota(dest, "/run/kmsg");
- to = prefix_roota(dest, "/proc/kmsg");
-
- if (mkfifo(from, 0600) < 0)
+ /* We create the kmsg FIFO as as temporary file in /tmp, but immediately delete it after bind mounting it to
+ * /proc/kmsg. While FIFOs on the reading side behave very similar to /proc/kmsg, their writing side behaves
+ * differently from /dev/kmsg in that writing blocks when nothing is reading. In order to avoid any problems
+ * with containers deadlocking due to this we simply make /dev/kmsg unavailable to the container. */
+
+ r = tempfn_random_child(NULL, "proc-kmsg", &fifo);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate kmsg path: %m");
+
+ if (mkfifo(fifo, 0600) < 0)
return log_error_errno(errno, "mkfifo() for /run/kmsg failed: %m");
+
+ from = TAKE_PTR(fifo);
+ to = "/proc/kmsg";
+
r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL);
if (r < 0)
return r;
- fd = open(from, O_RDWR|O_NDELAY|O_CLOEXEC);
+ fd = open(from, O_RDWR|O_NONBLOCK|O_CLOEXEC);
if (fd < 0)
return log_error_errno(errno, "Failed to open fifo: %m");
- /* Store away the fd in the socket, so that it stays open as
- * long as we run the child */
+ /* Store away the fd in the socket, so that it stays open as long as we run the child */
r = send_one_fd(kmsg_socket, fd, 0);
- safe_close(fd);
-
if (r < 0)
return log_error_errno(r, "Failed to send FIFO fd: %m");
- /* And now make the FIFO unavailable as /run/kmsg... */
- (void) unlink(from);
-
return 0;
}
@@ -1730,12 +1970,14 @@ static int on_address_change(sd_netlink *rtnl, sd_netlink_message *m, void *user
}
static int setup_hostname(void) {
+ int r;
if ((arg_clone_ns_flags & CLONE_NEWUTS) == 0)
return 0;
- if (sethostname_idempotent(arg_machine) < 0)
- return -errno;
+ r = sethostname_idempotent(arg_hostname ?: arg_machine);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set hostname: %m");
return 0;
}
@@ -1911,7 +2153,6 @@ static int reset_audit_loginuid(void) {
return 0;
}
-
static int setup_propagate(const char *root) {
const char *p, *q;
int r;
@@ -2146,13 +2387,11 @@ static int determine_names(void) {
if (arg_machine) {
_cleanup_(image_unrefp) Image *i = NULL;
- r = image_find(arg_machine, &i);
+ r = image_find(IMAGE_MACHINE, arg_machine, &i);
+ if (r == -ENOENT)
+ return log_error_errno(r, "No image for machine '%s'.", arg_machine);
if (r < 0)
return log_error_errno(r, "Failed to find image for machine '%s': %m", arg_machine);
- if (r == 0) {
- log_error("No image for machine '%s'.", arg_machine);
- return -ENOENT;
- }
if (IN_SET(i->type, IMAGE_RAW, IMAGE_BLOCK))
r = free_and_strdup(&arg_image, i->path);
@@ -2176,7 +2415,6 @@ static int determine_names(void) {
}
if (!arg_machine) {
-
if (arg_directory && path_equal(arg_directory, "/"))
arg_machine = gethostname_malloc();
else {
@@ -2280,9 +2518,9 @@ static int inner_child(
_cleanup_free_ char *home = NULL;
char as_uuid[37];
- unsigned n_env = 1;
+ size_t n_env = 1;
const char *envp[] = {
- "PATH=" DEFAULT_PATH_SPLIT_USR,
+ "PATH=" DEFAULT_PATH_COMPAT,
NULL, /* container */
NULL, /* TERM */
NULL, /* HOME */
@@ -2295,7 +2533,6 @@ static int inner_child(
NULL
};
const char *exec_target;
-
_cleanup_strv_free_ char **env_use = NULL;
int r;
@@ -2366,17 +2603,15 @@ static int inner_child(
return r;
}
- r = setup_boot_id(NULL);
+ r = setup_boot_id();
if (r < 0)
return r;
- r = setup_kmsg(NULL, kmsg_socket);
+ r = setup_kmsg(kmsg_socket);
if (r < 0)
return r;
kmsg_socket = safe_close(kmsg_socket);
- umask(0022);
-
if (setsid() < 0)
return log_error_errno(errno, "setsid() failed: %m");
@@ -2390,11 +2625,21 @@ static int inner_child(
rtnl_socket = safe_close(rtnl_socket);
}
+ if (arg_oom_score_adjust_set) {
+ r = set_oom_score_adjust(arg_oom_score_adjust);
+ if (r < 0)
+ return log_error_errno(r, "Failed to adjust OOM score: %m");
+ }
+
+ if (arg_cpuset)
+ if (sched_setaffinity(0, CPU_ALLOC_SIZE(arg_cpuset_ncpus), arg_cpuset) < 0)
+ return log_error_errno(errno, "Failed to set CPU affinity: %m");
+
r = drop_capabilities();
if (r < 0)
return log_error_errno(r, "drop_capabilities() failed: %m");
- setup_hostname();
+ (void) setup_hostname();
if (arg_personality != PERSONALITY_INVALID) {
r = safe_personality(arg_personality);
@@ -2416,6 +2661,10 @@ static int inner_child(
if (r < 0)
return r;
+ if (arg_no_new_privileges)
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
+ return log_error_errno(errno, "Failed to disable new privileges: %m");
+
/* LXC sets container=lxc, so follow the scheme here */
envp[n_env++] = strjoina("container=", arg_container_service_name);
@@ -2467,15 +2716,12 @@ static int inner_child(
return r;
}
- /* Now, explicitly close the log, so that we
- * then can close all remaining fds. Closing
- * the log explicitly first has the benefit
- * that the logging subsystem knows about it,
- * and is thus ready to be reopened should we
- * need it again. Note that the other fds
- * closed here are at least the locking and
- * barrier fds. */
+ /* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first
+ * has the benefit that the logging subsystem knows about it, and is thus ready to be reopened should we need
+ * it again. Note that the other fds closed here are at least the locking and barrier fds. */
log_close();
+ log_set_open_when_needed(true);
+
(void) fdset_close_others(fds);
if (arg_start_mode == START_BOOT) {
@@ -2513,9 +2759,7 @@ static int inner_child(
exec_target = "/bin/bash, /bin/sh";
}
- r = -errno;
- (void) log_open();
- return log_error_errno(r, "execv(%s) failed: %m", exec_target);
+ return log_error_errno(errno, "execv(%s) failed: %m", exec_target);
}
static int setup_sd_notify_child(void) {
@@ -2572,10 +2816,10 @@ static int outer_child(
FDSet *fds,
int netns_fd) {
+ _cleanup_close_ int fd = -1;
+ int r, which_failed;
pid_t pid;
ssize_t l;
- int r;
- _cleanup_close_ int fd = -1;
assert(barrier);
assert(directory);
@@ -2595,6 +2839,11 @@ static int outer_child(
if (terminal < 0)
return log_error_errno(terminal, "Failed to open console: %m");
+ /* Make sure we can continue logging to the original stderr, even if stderr points elsewhere now */
+ r = log_dup_console();
+ if (r < 0)
+ return log_error_errno(r, "Failed to duplicate stderr: %m");
+
r = rearrange_stdio(terminal, terminal, terminal); /* invalidates 'terminal' on success and failure */
if (r < 0)
return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");
@@ -2618,7 +2867,9 @@ static int outer_child(
* makes sure ESP partitions and userns are compatible. */
r = dissected_image_mount(dissected_image, directory, arg_uid_shift,
- DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP|(arg_read_only ? DISSECT_IMAGE_READ_ONLY : 0));
+ DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP|
+ (arg_read_only ? DISSECT_IMAGE_READ_ONLY : 0)|
+ (arg_start_mode == START_BOOT ? DISSECT_IMAGE_VALIDATE_OS : 0));
if (r < 0)
return r;
}
@@ -2673,7 +2924,7 @@ static int outer_child(
if (l < 0)
return log_error_errno(errno, "Failed to send cgroup mode: %m");
if (l != sizeof(arg_unified_cgroup_hierarchy)) {
- log_error("Short write while sending cgroup mode: %m");
+ log_error("Short write while sending cgroup mode.");
return -EIO;
}
@@ -2818,6 +3069,10 @@ static int outer_child(
if (fd < 0)
return fd;
+ r = setrlimit_closest_all((const struct rlimit *const*) arg_rlimit, &which_failed);
+ if (r < 0)
+ return log_error_errno(r, "Failed to apply resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed));
+
pid = raw_clone(SIGCHLD|CLONE_NEWNS|
arg_clone_ns_flags |
(arg_userns_mode != USER_NAMESPACE_NO ? CLONE_NEWUSER : 0));
@@ -2893,7 +3148,7 @@ static int uid_shift_pick(uid_t *shift, LockFile *ret_lock_file) {
for (;;) {
char lock_path[STRLEN("/run/systemd/nspawn-uid/") + DECIMAL_STR_MAX(uid_t) + 1];
- _cleanup_release_lock_file_ LockFile lf = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile lf = LOCK_FILE_INIT;
if (--n_tries <= 0)
return -EBUSY;
@@ -3054,88 +3309,19 @@ static int setup_sd_notify_parent(sd_event *event, int fd, pid_t *inner_child_pi
return 0;
}
-static int load_settings(void) {
- _cleanup_(settings_freep) Settings *settings = NULL;
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *p = NULL;
- const char *fn, *i;
- int r;
+static int merge_settings(Settings *settings, const char *path) {
+ int rl;
- /* If all settings are masked, there's no point in looking for
- * the settings file */
- if ((arg_settings_mask & _SETTINGS_MASK_ALL) == _SETTINGS_MASK_ALL)
- return 0;
+ assert(settings);
+ assert(path);
- fn = strjoina(arg_machine, ".nspawn");
-
- /* We first look in the admin's directories in /etc and /run */
- FOREACH_STRING(i, "/etc/systemd/nspawn", "/run/systemd/nspawn") {
- _cleanup_free_ char *j = NULL;
-
- j = strjoin(i, "/", fn);
- if (!j)
- return log_oom();
-
- f = fopen(j, "re");
- if (f) {
- p = j;
- j = NULL;
-
- /* By default, we trust configuration from /etc and /run */
- if (arg_settings_trusted < 0)
- arg_settings_trusted = true;
-
- break;
- }
-
- if (errno != ENOENT)
- return log_error_errno(errno, "Failed to open %s: %m", j);
- }
-
- if (!f) {
- /* After that, let's look for a file next to the
- * actual image we shall boot. */
-
- if (arg_image) {
- p = file_in_same_dir(arg_image, fn);
- if (!p)
- return log_oom();
- } else if (arg_directory) {
- p = file_in_same_dir(arg_directory, fn);
- if (!p)
- return log_oom();
- }
-
- if (p) {
- f = fopen(p, "re");
- if (!f && errno != ENOENT)
- return log_error_errno(errno, "Failed to open %s: %m", p);
-
- /* By default, we do not trust configuration from /var/lib/machines */
- if (arg_settings_trusted < 0)
- arg_settings_trusted = false;
- }
- }
-
- if (!f)
- return 0;
-
- log_debug("Settings are trusted: %s", yes_no(arg_settings_trusted));
-
- r = settings_load(f, p, &settings);
- if (r < 0)
- return r;
-
- /* Copy over bits from the settings, unless they have been
- * explicitly masked by command line switches. */
+ /* Copy over bits from the settings, unless they have been explicitly masked by command line switches. Note
+ * that this steals the fields of the Settings* structure, and hence modifies it. */
if ((arg_settings_mask & SETTING_START_MODE) == 0 &&
settings->start_mode >= 0) {
arg_start_mode = settings->start_mode;
-
- strv_free(arg_parameters);
- arg_parameters = settings->parameters;
- settings->parameters = NULL;
+ strv_free_and_replace(arg_parameters, settings->parameters);
}
if ((arg_settings_mask & SETTING_PIVOT_ROOT) == 0 &&
@@ -3145,25 +3331,16 @@ static int load_settings(void) {
}
if ((arg_settings_mask & SETTING_WORKING_DIRECTORY) == 0 &&
- settings->working_directory) {
- free(arg_chdir);
- arg_chdir = settings->working_directory;
- settings->working_directory = NULL;
- }
+ settings->working_directory)
+ free_and_replace(arg_chdir, settings->working_directory);
if ((arg_settings_mask & SETTING_ENVIRONMENT) == 0 &&
- settings->environment) {
- strv_free(arg_setenv);
- arg_setenv = settings->environment;
- settings->environment = NULL;
- }
+ settings->environment)
+ strv_free_and_replace(arg_setenv, settings->environment);
if ((arg_settings_mask & SETTING_USER) == 0 &&
- settings->user) {
- free(arg_user);
- arg_user = settings->user;
- settings->user = NULL;
- }
+ settings->user)
+ free_and_replace(arg_user, settings->user);
if ((arg_settings_mask & SETTING_CAPABILITY) == 0) {
uint64_t plus;
@@ -3174,7 +3351,7 @@ static int load_settings(void) {
if (!arg_settings_trusted && plus != 0) {
if (settings->capability != 0)
- log_warning("Ignoring Capability= setting, file %s is not trusted.", p);
+ log_warning("Ignoring Capability= setting, file %s is not trusted.", path);
} else
arg_caps_retain |= plus;
@@ -3193,7 +3370,7 @@ static int load_settings(void) {
!sd_id128_is_null(settings->machine_id)) {
if (!arg_settings_trusted)
- log_warning("Ignoring MachineID= setting, file %s is not trusted.", p);
+ log_warning("Ignoring MachineID= setting, file %s is not trusted.", path);
else
arg_uuid = settings->machine_id;
}
@@ -3210,13 +3387,11 @@ static int load_settings(void) {
settings->n_custom_mounts > 0) {
if (!arg_settings_trusted)
- log_warning("Ignoring TemporaryFileSystem=, Bind= and BindReadOnly= settings, file %s is not trusted.", p);
+ log_warning("Ignoring TemporaryFileSystem=, Bind= and BindReadOnly= settings, file %s is not trusted.", path);
else {
custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts);
- arg_custom_mounts = settings->custom_mounts;
+ arg_custom_mounts = TAKE_PTR(settings->custom_mounts);
arg_n_custom_mounts = settings->n_custom_mounts;
-
- settings->custom_mounts = NULL;
settings->n_custom_mounts = 0;
}
}
@@ -3232,34 +3407,18 @@ static int load_settings(void) {
settings->network_veth_extra)) {
if (!arg_settings_trusted)
- log_warning("Ignoring network settings, file %s is not trusted.", p);
+ log_warning("Ignoring network settings, file %s is not trusted.", path);
else {
arg_network_veth = settings_network_veth(settings);
arg_private_network = settings_private_network(settings);
- strv_free(arg_network_interfaces);
- arg_network_interfaces = settings->network_interfaces;
- settings->network_interfaces = NULL;
-
- strv_free(arg_network_macvlan);
- arg_network_macvlan = settings->network_macvlan;
- settings->network_macvlan = NULL;
+ strv_free_and_replace(arg_network_interfaces, settings->network_interfaces);
+ strv_free_and_replace(arg_network_macvlan, settings->network_macvlan);
+ strv_free_and_replace(arg_network_ipvlan, settings->network_ipvlan);
+ strv_free_and_replace(arg_network_veth_extra, settings->network_veth_extra);
- strv_free(arg_network_ipvlan);
- arg_network_ipvlan = settings->network_ipvlan;
- settings->network_ipvlan = NULL;
-
- strv_free(arg_network_veth_extra);
- arg_network_veth_extra = settings->network_veth_extra;
- settings->network_veth_extra = NULL;
-
- free(arg_network_bridge);
- arg_network_bridge = settings->network_bridge;
- settings->network_bridge = NULL;
-
- free(arg_network_zone);
- arg_network_zone = settings->network_zone;
- settings->network_zone = NULL;
+ free_and_replace(arg_network_bridge, settings->network_bridge);
+ free_and_replace(arg_network_zone, settings->network_zone);
}
}
@@ -3267,11 +3426,10 @@ static int load_settings(void) {
settings->expose_ports) {
if (!arg_settings_trusted)
- log_warning("Ignoring Port= setting, file %s is not trusted.", p);
+ log_warning("Ignoring Port= setting, file %s is not trusted.", path);
else {
expose_port_free_all(arg_expose_ports);
- arg_expose_ports = settings->expose_ports;
- settings->expose_ports = NULL;
+ arg_expose_ports = TAKE_PTR(settings->expose_ports);
}
}
@@ -3279,7 +3437,7 @@ static int load_settings(void) {
settings->userns_mode != _USER_NAMESPACE_MODE_INVALID) {
if (!arg_settings_trusted)
- log_warning("Ignoring PrivateUsers= and PrivateUsersChown= settings, file %s is not trusted.", p);
+ log_warning("Ignoring PrivateUsers= and PrivateUsersChown= settings, file %s is not trusted.", path);
else {
arg_userns_mode = settings->userns_mode;
arg_uid_shift = settings->uid_shift;
@@ -3294,21 +3452,156 @@ static int load_settings(void) {
if ((arg_settings_mask & SETTING_SYSCALL_FILTER) == 0) {
if (!arg_settings_trusted && !strv_isempty(arg_syscall_whitelist))
- log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", p);
+ log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", path);
else {
- strv_free(arg_syscall_whitelist);
- strv_free(arg_syscall_blacklist);
+ strv_free_and_replace(arg_syscall_whitelist, settings->syscall_whitelist);
+ strv_free_and_replace(arg_syscall_blacklist, settings->syscall_blacklist);
+ }
+ }
+
+ for (rl = 0; rl < _RLIMIT_MAX; rl ++) {
+ if ((arg_settings_mask & (SETTING_RLIMIT_FIRST << rl)))
+ continue;
- arg_syscall_whitelist = settings->syscall_whitelist;
- arg_syscall_blacklist = settings->syscall_blacklist;
+ if (!settings->rlimit[rl])
+ continue;
- settings->syscall_whitelist = settings->syscall_blacklist = NULL;
+ if (!arg_settings_trusted) {
+ log_warning("Ignoring Limit%s= setting, file '%s' is not trusted.", rlimit_to_string(rl), path);
+ continue;
}
+
+ free_and_replace(arg_rlimit[rl], settings->rlimit[rl]);
}
+ if ((arg_settings_mask & SETTING_HOSTNAME) == 0 &&
+ settings->hostname)
+ free_and_replace(arg_hostname, settings->hostname);
+
+ if ((arg_settings_mask & SETTING_NO_NEW_PRIVILEGES) == 0 &&
+ settings->no_new_privileges >= 0)
+ arg_no_new_privileges = settings->no_new_privileges;
+
+ if ((arg_settings_mask & SETTING_OOM_SCORE_ADJUST) == 0 &&
+ settings->oom_score_adjust_set) {
+
+ if (!arg_settings_trusted)
+ log_warning("Ignoring OOMScoreAdjust= setting, file '%s' is not trusted.", path);
+ else {
+ arg_oom_score_adjust = settings->oom_score_adjust;
+ arg_oom_score_adjust_set = true;
+ }
+ }
+
+ if ((arg_settings_mask & SETTING_CPU_AFFINITY) == 0 &&
+ settings->cpuset) {
+
+ if (!arg_settings_trusted)
+ log_warning("Ignoring CPUAffinity= setting, file '%s' is not trusted.", path);
+ else {
+ if (arg_cpuset)
+ CPU_FREE(arg_cpuset);
+ arg_cpuset = TAKE_PTR(settings->cpuset);
+ arg_cpuset_ncpus = settings->cpuset_ncpus;
+ }
+ }
+
+ if ((arg_settings_mask & SETTING_RESOLV_CONF) == 0 &&
+ settings->resolv_conf != _RESOLV_CONF_MODE_INVALID)
+ arg_resolv_conf = settings->resolv_conf;
+
+ if ((arg_settings_mask & SETTING_LINK_JOURNAL) == 0 &&
+ settings->link_journal != _LINK_JOURNAL_INVALID) {
+
+ if (!arg_settings_trusted)
+ log_warning("Ignoring journal link setting, file '%s' is not trusted.", path);
+ else {
+ arg_link_journal = settings->link_journal;
+ arg_link_journal_try = settings->link_journal_try;
+ }
+ }
+
+ if ((arg_settings_mask & SETTING_TIMEZONE) == 0 &&
+ settings->timezone != _TIMEZONE_MODE_INVALID)
+ arg_timezone = settings->timezone;
+
return 0;
}
+static int load_settings(void) {
+ _cleanup_(settings_freep) Settings *settings = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ const char *fn, *i;
+ int r;
+
+ /* If all settings are masked, there's no point in looking for
+ * the settings file */
+ if ((arg_settings_mask & _SETTINGS_MASK_ALL) == _SETTINGS_MASK_ALL)
+ return 0;
+
+ fn = strjoina(arg_machine, ".nspawn");
+
+ /* We first look in the admin's directories in /etc and /run */
+ FOREACH_STRING(i, "/etc/systemd/nspawn", "/run/systemd/nspawn") {
+ _cleanup_free_ char *j = NULL;
+
+ j = strjoin(i, "/", fn);
+ if (!j)
+ return log_oom();
+
+ f = fopen(j, "re");
+ if (f) {
+ p = TAKE_PTR(j);
+
+ /* By default, we trust configuration from /etc and /run */
+ if (arg_settings_trusted < 0)
+ arg_settings_trusted = true;
+
+ break;
+ }
+
+ if (errno != ENOENT)
+ return log_error_errno(errno, "Failed to open %s: %m", j);
+ }
+
+ if (!f) {
+ /* After that, let's look for a file next to the
+ * actual image we shall boot. */
+
+ if (arg_image) {
+ p = file_in_same_dir(arg_image, fn);
+ if (!p)
+ return log_oom();
+ } else if (arg_directory) {
+ p = file_in_same_dir(arg_directory, fn);
+ if (!p)
+ return log_oom();
+ }
+
+ if (p) {
+ f = fopen(p, "re");
+ if (!f && errno != ENOENT)
+ return log_error_errno(errno, "Failed to open %s: %m", p);
+
+ /* By default, we do not trust configuration from /var/lib/machines */
+ if (arg_settings_trusted < 0)
+ arg_settings_trusted = false;
+ }
+ }
+
+ if (!f)
+ return 0;
+
+ log_debug("Settings are trusted: %s", yes_no(arg_settings_trusted));
+
+ r = settings_load(f, p, &settings);
+ if (r < 0)
+ return r;
+
+ return merge_settings(settings, p);
+}
+
static int run(int master,
const char* console,
DissectedImage *dissected_image,
@@ -3324,7 +3617,7 @@ static int run(int master,
.sa_flags = SA_NOCLDSTOP|SA_RESTART,
};
- _cleanup_release_lock_file_ LockFile uid_shift_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile uid_shift_lock = LOCK_FILE_INIT;
_cleanup_close_ int etc_passwd_lock = -1;
_cleanup_close_pair_ int
kmsg_socket_pair[2] = { -1, -1 },
@@ -3559,7 +3852,6 @@ static int run(int master,
}
if (arg_private_network) {
-
if (!arg_network_namespace_path) {
/* Wait until the child has unshared its network namespace. */
if (!barrier_place_and_sync(&barrier)) { /* #3 */
@@ -3640,7 +3932,6 @@ static int run(int master,
}
if (arg_register) {
-
r = register_machine(
bus,
arg_machine,
@@ -3658,7 +3949,6 @@ static int run(int master,
return r;
} else if (!arg_keep_unit) {
-
r = allocate_scope(
bus,
arg_machine,
@@ -3677,11 +3967,9 @@ static int run(int master,
if (r < 0)
return r;
- if (arg_keep_unit) {
- r = create_subcgroup(*pid, arg_unified_cgroup_hierarchy);
- if (r < 0)
- return r;
- }
+ r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
+ if (r < 0)
+ return r;
r = chown_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
if (r < 0)
@@ -3732,20 +4020,20 @@ static int run(int master,
"STATUS=Container running.\n"
"X_NSPAWN_LEADER_PID=" PID_FMT, *pid);
if (!arg_notify_ready)
- sd_notify(false, "READY=1\n");
+ (void) sd_notify(false, "READY=1\n");
if (arg_kill_signal > 0) {
/* Try to kill the init system on SIGINT or SIGTERM */
- sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(*pid));
- sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(*pid));
+ (void) sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(*pid));
+ (void) sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(*pid));
} else {
/* Immediately exit */
- sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
- sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+ (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+ (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
}
/* Exit when the child exits */
- sd_event_add_signal(event, NULL, SIGCHLD, on_sigchld, PID_TO_PTR(*pid));
+ (void) sd_event_add_signal(event, NULL, SIGCHLD, on_sigchld, PID_TO_PTR(*pid));
if (arg_expose_ports) {
r = expose_port_watch_rtnl(event, rtnl_socket_pair[0], on_address_change, exposed, &rtnl);
@@ -3819,8 +4107,70 @@ static int run(int master,
return 1; /* loop again */
}
-int main(int argc, char *argv[]) {
+static int initialize_rlimits(void) {
+ /* The default resource limits the kernel passes to PID 1, as per kernel 4.16. Let's pass our container payload
+ * the same values as the kernel originally passed to PID 1, in order to minimize differences between host and
+ * container execution environments. */
+
+ static const struct rlimit kernel_defaults[_RLIMIT_MAX] = {
+ [RLIMIT_AS] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_CORE] = { 0, RLIM_INFINITY },
+ [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_MEMLOCK] = { 65536, 65536 },
+ [RLIMIT_MSGQUEUE] = { 819200, 819200 },
+ [RLIMIT_NICE] = { 0, 0 },
+ [RLIMIT_NOFILE] = { 1024, 4096 },
+ [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_RTPRIO] = { 0, 0 },
+ [RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_STACK] = { 8388608, RLIM_INFINITY },
+
+ /* The kernel scales the default for RLIMIT_NPROC and RLIMIT_SIGPENDING based on the system's amount of
+ * RAM. To provide best compatibility we'll read these limits off PID 1 instead of hardcoding them
+ * here. This is safe as we know that PID 1 doesn't change these two limits and thus the original
+ * kernel's initialization should still be valid during runtime — at least if PID 1 is systemd. Note
+ * that PID 1 changes a number of other resource limits during early initialization which is why we
+ * don't read the other limits from PID 1 but prefer the static table above. */
+ };
+
+ int rl;
+
+ for (rl = 0; rl < _RLIMIT_MAX; rl++) {
+ /* Let's only fill in what the user hasn't explicitly configured anyway */
+ if ((arg_settings_mask & (SETTING_RLIMIT_FIRST << rl)) == 0) {
+ const struct rlimit *v;
+ struct rlimit buffer;
+ if (IN_SET(rl, RLIMIT_NPROC, RLIMIT_SIGPENDING)) {
+ /* For these two let's read the limits off PID 1. See above for an explanation. */
+
+ if (prlimit(1, rl, NULL, &buffer) < 0)
+ return log_error_errno(errno, "Failed to read resource limit RLIMIT_%s of PID 1: %m", rlimit_to_string(rl));
+
+ v = &buffer;
+ } else
+ v = kernel_defaults + rl;
+
+ arg_rlimit[rl] = newdup(struct rlimit, v, 1);
+ if (!arg_rlimit[rl])
+ return log_oom();
+ }
+
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *k = NULL;
+
+ (void) rlimit_format(arg_rlimit[rl], &k);
+ log_debug("Setting RLIMIT_%s to %s.", rlimit_to_string(rl), k);
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
_cleanup_free_ char *console = NULL;
_cleanup_close_ int master = -1;
_cleanup_fdset_free_ FDSet *fds = NULL;
@@ -3829,7 +4179,7 @@ int main(int argc, char *argv[]) {
bool secondary = false, remove_directory = false, remove_image = false;
pid_t pid = 0;
union in_addr_union exposed = {};
- _cleanup_release_lock_file_ LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT;
bool interactive, veth_created = false, remove_tmprootdir = false;
char tmprootdir[] = "/tmp/nspawn-root-XXXXXX";
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
@@ -3851,6 +4201,10 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
+ r = initialize_rlimits();
+ if (r < 0)
+ goto finish;
+
r = determine_names();
if (r < 0)
goto finish;
@@ -3876,6 +4230,11 @@ int main(int argc, char *argv[]) {
}
}
+ /* The "default" umask. This is appropriate for most file and directory
+ * operations performed by nspawn, and is the umask that will be used for
+ * the child. Functions like copy_devnodes() change the umask temporarily. */
+ umask(0022);
+
if (arg_directory) {
assert(!arg_image);
@@ -3929,9 +4288,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- free(arg_directory);
- arg_directory = np;
- np = NULL;
+ free_and_replace(arg_directory, np);
remove_directory = true;
@@ -3976,17 +4333,30 @@ int main(int argc, char *argv[]) {
}
if (arg_start_mode == START_BOOT) {
- if (path_is_os_tree(arg_directory) <= 0) {
- log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", arg_directory);
+ const char *p;
+
+ if (arg_pivot_root_new)
+ p = prefix_roota(arg_directory, arg_pivot_root_new);
+ else
+ p = arg_directory;
+
+ if (path_is_os_tree(p) <= 0) {
+ log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", p);
r = -EINVAL;
goto finish;
}
} else {
- const char *p;
+ const char *p, *q;
+
+ if (arg_pivot_root_new)
+ p = prefix_roota(arg_directory, arg_pivot_root_new);
+ else
+ p = arg_directory;
+
+ q = strjoina(p, "/usr/");
- p = strjoina(arg_directory, "/usr/");
- if (laccess(p, F_OK) < 0) {
- log_error("Directory %s doesn't look like it has an OS tree. Refusing.", arg_directory);
+ if (laccess(q, F_OK) < 0) {
+ log_error("Directory %s doesn't look like it has an OS tree. Refusing.", p);
r = -EINVAL;
goto finish;
}
@@ -4021,9 +4391,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- free(arg_image);
- arg_image = np;
- np = NULL;
+ free_and_replace(arg_image, np);
remove_image = true;
} else {
@@ -4065,14 +4433,14 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = dissect_image(
+ r = dissect_image_and_warn(
loop->fd,
+ arg_image,
arg_root_hash, arg_root_hash_size,
DISSECT_IMAGE_REQUIRE_ROOT,
&dissected_image);
if (r == -ENOPKG) {
- log_error_errno(r, "Could not find a suitable file system or partition table in image: %s", arg_image);
-
+ /* dissected_image_and_warn() already printed a brief error message. Extend on that with more details */
log_notice("Note that the disk image needs to\n"
" a) either contain only a single MBR partition of type 0x83 that is marked bootable\n"
" b) or contain a single GPT partition of type 0FC63DAF-8483-4772-8E79-3D69D8477DE4\n"
@@ -4081,22 +4449,8 @@ int main(int argc, char *argv[]) {
"in order to be bootable with systemd-nspawn.");
goto finish;
}
- if (r == -EADDRNOTAVAIL) {
- log_error_errno(r, "No root partition for specified root hash found.");
- goto finish;
- }
- if (r == -EOPNOTSUPP) {
- log_error_errno(r, "--image= is not supported, compiled without blkid support.");
- goto finish;
- }
- if (r == -EPROTONOSUPPORT) {
- log_error_errno(r, "Device is loopback block device with partition scanning turned off, please turn it on.");
- goto finish;
- }
- if (r < 0) {
- log_error_errno(r, "Failed to dissect image: %m");
+ if (r < 0)
goto finish;
- }
if (!arg_root_hash && dissected_image->can_verity)
log_notice("Note: image %s contains verity information, but no root hash specified! Proceeding without integrity checking.", arg_image);
@@ -4118,7 +4472,7 @@ int main(int argc, char *argv[]) {
isatty(STDIN_FILENO) > 0 &&
isatty(STDOUT_FILENO) > 0;
- master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
+ master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (master < 0) {
r = log_error_errno(errno, "Failed to acquire pseudo tty: %m");
goto finish;
@@ -4147,7 +4501,7 @@ int main(int argc, char *argv[]) {
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
- if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) {
+ if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) < 0) {
r = log_error_errno(errno, "Failed to become subreaper: %m");
goto finish;
}
@@ -4182,6 +4536,8 @@ finish:
if (pid > 0)
(void) wait_for_terminate(pid, NULL);
+ pager_close();
+
if (remove_directory && arg_directory) {
int k;
@@ -4217,6 +4573,7 @@ finish:
free(arg_template);
free(arg_image);
free(arg_machine);
+ free(arg_hostname);
free(arg_user);
free(arg_pivot_root_new);
free(arg_pivot_root_old);
@@ -4228,9 +4585,16 @@ finish:
strv_free(arg_network_ipvlan);
strv_free(arg_network_veth_extra);
strv_free(arg_parameters);
+ free(arg_network_zone);
+ free(arg_network_namespace_path);
+ strv_free(arg_property);
custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts);
expose_port_free_all(arg_expose_ports);
free(arg_root_hash);
+ rlimit_free_all(arg_rlimit);
+ strv_free(arg_syscall_whitelist);
+ strv_free(arg_syscall_blacklist);
+ arg_cpuset = cpu_set_mfree(arg_cpuset);
return r < 0 ? EXIT_FAILURE : ret;
}
diff --git a/src/nspawn/test-nspawn-tables.c b/src/nspawn/test-nspawn-tables.c
new file mode 100644
index 0000000000..2c5f2ef6db
--- /dev/null
+++ b/src/nspawn/test-nspawn-tables.c
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "nspawn-settings.h"
+#include "test-tables.h"
+
+int main(int argc, char **argv) {
+ test_table(resolv_conf_mode, RESOLV_CONF_MODE);
+ test_table(timezone_mode, TIMEZONE_MODE);
+
+ return 0;
+}
diff --git a/src/nspawn/test-patch-uid.c b/src/nspawn/test-patch-uid.c
index cdc438f269..8e29d3e806 100644
--- a/src/nspawn/test-patch-uid.c
+++ b/src/nspawn/test-patch-uid.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdlib.h>
diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c
index 39714fe3c2..f82ce59f2c 100644
--- a/src/nss-myhostname/nss-myhostname.c
+++ b/src/nss-myhostname/nss-myhostname.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-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 <net/if.h>
diff --git a/src/nss-myhostname/nss-myhostname.sym b/src/nss-myhostname/nss-myhostname.sym
index 0dcdb9bd40..fc7aa99574 100644
--- a/src/nss-myhostname/nss-myhostname.sym
+++ b/src/nss-myhostname/nss-myhostname.sym
@@ -1,8 +1,6 @@
/***
SPDX-License-Identifier: LGPL-2.1+
- 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
diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c
index 8a665cba3e..8d6caa0ada 100644
--- a/src/nss-mymachines/nss-mymachines.c
+++ b/src/nss-mymachines/nss-mymachines.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netdb.h>
#include <nss.h>
@@ -507,7 +489,7 @@ enum nss_status _nss_mymachines_getpwuid_r(
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- const char *machine, *object;
+ const char *machine;
uint32_t mapped;
int r;
@@ -543,7 +525,7 @@ enum nss_status _nss_mymachines_getpwuid_r(
goto fail;
}
- r = sd_bus_message_read(reply, "sou", &machine, &object, &mapped);
+ r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped);
if (r < 0)
goto fail;
@@ -656,7 +638,7 @@ enum nss_status _nss_mymachines_getgrnam_r(
strcpy(buffer + sizeof(char*), name);
gr->gr_name = buffer + sizeof(char*);
- gr->gr_gid = gid;
+ gr->gr_gid = mapped;
gr->gr_passwd = (char*) "*"; /* locked */
gr->gr_mem = (char**) buffer;
@@ -681,7 +663,7 @@ enum nss_status _nss_mymachines_getgrgid_r(
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- const char *machine, *object;
+ const char *machine;
uint32_t mapped;
int r;
@@ -717,7 +699,7 @@ enum nss_status _nss_mymachines_getgrgid_r(
goto fail;
}
- r = sd_bus_message_read(reply, "sou", &machine, &object, &mapped);
+ r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped);
if (r < 0)
goto fail;
diff --git a/src/nss-mymachines/nss-mymachines.sym b/src/nss-mymachines/nss-mymachines.sym
index 056d4276f9..ade64474a2 100644
--- a/src/nss-mymachines/nss-mymachines.sym
+++ b/src/nss-mymachines/nss-mymachines.sym
@@ -1,8 +1,6 @@
/***
SPDX-License-Identifier: LGPL-2.1+
- 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
diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c
index fe6ce4cbbf..eb3d2d977f 100644
--- a/src/nss-resolve/nss-resolve.c
+++ b/src/nss-resolve/nss-resolve.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <netdb.h>
diff --git a/src/nss-resolve/nss-resolve.sym b/src/nss-resolve/nss-resolve.sym
index 27570dfce4..e690a0092f 100644
--- a/src/nss-resolve/nss-resolve.sym
+++ b/src/nss-resolve/nss-resolve.sym
@@ -1,8 +1,6 @@
/***
SPDX-License-Identifier: LGPL-2.1+
- 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
diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c
index c502b5f5fd..f516b84c63 100644
--- a/src/nss-systemd/nss-systemd.c
+++ b/src/nss-systemd/nss-systemd.c
@@ -1,31 +1,17 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <nss.h>
+#include <pthread.h>
#include "sd-bus.h"
#include "alloc-util.h"
#include "bus-common-errors.h"
+#include "dirent-util.h"
#include "env-util.h"
+#include "fd-util.h"
#include "fs-util.h"
+#include "list.h"
#include "macro.h"
#include "nss-util.h"
#include "signal-util.h"
@@ -34,6 +20,11 @@
#include "user-util.h"
#include "util.h"
+#define DYNAMIC_USER_GECOS "Dynamic User"
+#define DYNAMIC_USER_PASSWD "*" /* locked */
+#define DYNAMIC_USER_DIR "/"
+#define DYNAMIC_USER_SHELL "/sbin/nologin"
+
static const struct passwd root_passwd = {
.pw_name = (char*) "root",
.pw_passwd = (char*) "x", /* see shadow file */
@@ -68,8 +59,40 @@ static const struct group nobody_group = {
.gr_mem = (char*[]) { NULL },
};
+typedef struct UserEntry UserEntry;
+typedef struct GetentData GetentData;
+
+struct UserEntry {
+ uid_t id;
+ char *name;
+
+ GetentData *data;
+ LIST_FIELDS(UserEntry, entries);
+};
+
+struct GetentData {
+ /* As explained in NOTES section of getpwent_r(3) as 'getpwent_r() is not really
+ * reentrant since it shares the reading position in the stream with all other threads',
+ * we need to protect the data in UserEntry from multithreaded programs which may call
+ * setpwent(), getpwent_r(), or endpwent() simultaneously. So, each function locks the
+ * data by using the mutex below. */
+ pthread_mutex_t mutex;
+
+ UserEntry *position;
+ LIST_HEAD(UserEntry, entries);
+};
+
+static GetentData getpwent_data = { PTHREAD_MUTEX_INITIALIZER, NULL, NULL };
+static GetentData getgrent_data = { PTHREAD_MUTEX_INITIALIZER, NULL, NULL };
+
NSS_GETPW_PROTOTYPES(systemd);
NSS_GETGR_PROTOTYPES(systemd);
+enum nss_status _nss_systemd_endpwent(void) _public_;
+enum nss_status _nss_systemd_setpwent(int stayopen) _public_;
+enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) _public_;
+enum nss_status _nss_systemd_endgrent(void) _public_;
+enum nss_status _nss_systemd_setgrent(int stayopen) _public_;
+enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) _public_;
static int direct_lookup_name(const char *name, uid_t *ret) {
_cleanup_free_ char *s = NULL;
@@ -115,6 +138,9 @@ enum nss_status _nss_systemd_getpwnam_r(
char *buffer, size_t buflen,
int *errnop) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
uint32_t translated;
size_t l;
int bypass, r;
@@ -150,16 +176,18 @@ enum nss_status _nss_systemd_getpwnam_r(
bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS");
if (bypass <= 0) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-
r = sd_bus_open_system(&bus);
- if (r < 0) {
+ if (r < 0)
bypass = 1;
- goto direct_lookup;
- }
+ }
+ if (bypass > 0) {
+ r = direct_lookup_name(name, (uid_t*) &translated);
+ if (r == -ENOENT)
+ goto not_found;
+ if (r < 0)
+ goto fail;
+ } else {
r = sd_bus_call_method(bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
@@ -181,16 +209,6 @@ enum nss_status _nss_systemd_getpwnam_r(
goto fail;
}
-direct_lookup:
- if (bypass > 0) {
- /* Access the dynamic UID allocation directly if we are called from dbus-daemon, see above. */
- r = direct_lookup_name(name, (uid_t*) &translated);
- if (r == -ENOENT)
- goto not_found;
- if (r < 0)
- goto fail;
- }
-
l = strlen(name);
if (buflen < l+1) {
*errnop = ERANGE;
@@ -202,10 +220,10 @@ direct_lookup:
pwd->pw_name = buffer;
pwd->pw_uid = (uid_t) translated;
pwd->pw_gid = (uid_t) translated;
- pwd->pw_gecos = (char*) "Dynamic User";
- pwd->pw_passwd = (char*) "*"; /* locked */
- pwd->pw_dir = (char*) "/";
- pwd->pw_shell = (char*) "/sbin/nologin";
+ pwd->pw_gecos = (char*) DYNAMIC_USER_GECOS;
+ pwd->pw_passwd = (char*) DYNAMIC_USER_PASSWD;
+ pwd->pw_dir = (char*) DYNAMIC_USER_DIR;
+ pwd->pw_shell = (char*) DYNAMIC_USER_SHELL;
*errnop = 0;
return NSS_STATUS_SUCCESS;
@@ -262,11 +280,20 @@ enum nss_status _nss_systemd_getpwuid_r(
bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS");
if (bypass <= 0) {
r = sd_bus_open_system(&bus);
- if (r < 0) {
+ if (r < 0)
bypass = 1;
- goto direct_lookup;
- }
+ }
+ if (bypass > 0) {
+ r = direct_lookup_uid(uid, &direct);
+ if (r == -ENOENT)
+ goto not_found;
+ if (r < 0)
+ goto fail;
+
+ translated = direct;
+
+ } else {
r = sd_bus_call_method(bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
@@ -288,18 +315,6 @@ enum nss_status _nss_systemd_getpwuid_r(
goto fail;
}
-direct_lookup:
- if (bypass > 0) {
- r = direct_lookup_uid(uid, &direct);
- if (r == -ENOENT)
- goto not_found;
- if (r < 0)
- goto fail;
-
- translated = direct;
-
- }
-
l = strlen(translated) + 1;
if (buflen < l) {
*errnop = ERANGE;
@@ -311,10 +326,10 @@ direct_lookup:
pwd->pw_name = buffer;
pwd->pw_uid = uid;
pwd->pw_gid = uid;
- pwd->pw_gecos = (char*) "Dynamic User";
- pwd->pw_passwd = (char*) "*"; /* locked */
- pwd->pw_dir = (char*) "/";
- pwd->pw_shell = (char*) "/sbin/nologin";
+ pwd->pw_gecos = (char*) DYNAMIC_USER_GECOS;
+ pwd->pw_passwd = (char*) DYNAMIC_USER_PASSWD;
+ pwd->pw_dir = (char*) DYNAMIC_USER_DIR;
+ pwd->pw_shell = (char*) DYNAMIC_USER_SHELL;
*errnop = 0;
return NSS_STATUS_SUCCESS;
@@ -336,6 +351,9 @@ enum nss_status _nss_systemd_getgrnam_r(
char *buffer, size_t buflen,
int *errnop) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
uint32_t translated;
size_t l;
int bypass, r;
@@ -368,16 +386,18 @@ enum nss_status _nss_systemd_getgrnam_r(
bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS");
if (bypass <= 0) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-
r = sd_bus_open_system(&bus);
- if (r < 0) {
+ if (r < 0)
bypass = 1;
- goto direct_lookup;
- }
+ }
+ if (bypass > 0) {
+ r = direct_lookup_name(name, (uid_t*) &translated);
+ if (r == -ENOENT)
+ goto not_found;
+ if (r < 0)
+ goto fail;
+ } else {
r = sd_bus_call_method(bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
@@ -399,16 +419,6 @@ enum nss_status _nss_systemd_getgrnam_r(
goto fail;
}
-direct_lookup:
- if (bypass > 0) {
- /* Access the dynamic GID allocation directly if we are called from dbus-daemon, see above. */
- r = direct_lookup_name(name, (uid_t*) &translated);
- if (r == -ENOENT)
- goto not_found;
- if (r < 0)
- goto fail;
- }
-
l = sizeof(char*) + strlen(name) + 1;
if (buflen < l) {
*errnop = ERANGE;
@@ -420,7 +430,7 @@ direct_lookup:
gr->gr_name = buffer + sizeof(char*);
gr->gr_gid = (gid_t) translated;
- gr->gr_passwd = (char*) "*"; /* locked */
+ gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD;
gr->gr_mem = (char**) buffer;
*errnop = 0;
@@ -478,11 +488,20 @@ enum nss_status _nss_systemd_getgrgid_r(
bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS");
if (bypass <= 0) {
r = sd_bus_open_system(&bus);
- if (r < 0) {
+ if (r < 0)
bypass = 1;
- goto direct_lookup;
- }
+ }
+
+ if (bypass > 0) {
+ r = direct_lookup_uid(gid, &direct);
+ if (r == -ENOENT)
+ goto not_found;
+ if (r < 0)
+ goto fail;
+ translated = direct;
+
+ } else {
r = sd_bus_call_method(bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
@@ -504,17 +523,6 @@ enum nss_status _nss_systemd_getgrgid_r(
goto fail;
}
-direct_lookup:
- if (bypass > 0) {
- r = direct_lookup_uid(gid, &direct);
- if (r == -ENOENT)
- goto not_found;
- if (r < 0)
- goto fail;
-
- translated = direct;
- }
-
l = sizeof(char*) + strlen(translated) + 1;
if (buflen < l) {
*errnop = ERANGE;
@@ -526,7 +534,7 @@ direct_lookup:
gr->gr_name = buffer + sizeof(char*);
gr->gr_gid = gid;
- gr->gr_passwd = (char*) "*"; /* locked */
+ gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD;
gr->gr_mem = (char**) buffer;
*errnop = 0;
@@ -540,3 +548,299 @@ fail:
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
+
+static void user_entry_free(UserEntry *p) {
+ if (!p)
+ return;
+
+ if (p->data)
+ LIST_REMOVE(entries, p->data->entries, p);
+
+ free(p->name);
+ free(p);
+}
+
+static int user_entry_add(GetentData *data, const char *name, uid_t id) {
+ UserEntry *p;
+
+ assert(data);
+
+ /* This happens when User= or Group= already exists statically. */
+ if (!uid_is_dynamic(id))
+ return -EINVAL;
+
+ p = new0(UserEntry, 1);
+ if (!p)
+ return -ENOMEM;
+
+ p->name = strdup(name);
+ if (!p->name) {
+ free(p);
+ return -ENOMEM;
+ }
+ p->id = id;
+ p->data = data;
+
+ LIST_PREPEND(entries, data->entries, p);
+
+ return 0;
+}
+
+static void systemd_endent(GetentData *data) {
+ UserEntry *p;
+
+ assert(data);
+
+ while ((p = data->entries))
+ user_entry_free(p);
+
+ data->position = NULL;
+}
+
+static enum nss_status nss_systemd_endent(GetentData *p) {
+ BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
+ assert_se(pthread_mutex_lock(&p->mutex) == 0);
+ systemd_endent(p);
+ assert_se(pthread_mutex_unlock(&p->mutex) == 0);
+
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status _nss_systemd_endpwent(void) {
+ return nss_systemd_endent(&getpwent_data);
+}
+
+enum nss_status _nss_systemd_endgrent(void) {
+ return nss_systemd_endent(&getgrent_data);
+}
+
+static int direct_enumeration(GetentData *p) {
+ _cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
+ int r;
+
+ assert(p);
+
+ d = opendir("/run/systemd/dynamic-uid/");
+ if (!d)
+ return -errno;
+
+ FOREACH_DIRENT(de, d, return -errno) {
+ _cleanup_free_ char *name = NULL;
+ uid_t uid, verified;
+
+ if (!dirent_is_file(de))
+ continue;
+
+ r = parse_uid(de->d_name, &uid);
+ if (r < 0)
+ continue;
+
+ r = direct_lookup_uid(uid, &name);
+ if (r == -ENOMEM)
+ return r;
+ if (r < 0)
+ continue;
+
+ r = direct_lookup_name(name, &verified);
+ if (r < 0)
+ continue;
+
+ if (uid != verified)
+ continue;
+
+ r = user_entry_add(p, name, uid);
+ if (r == -ENOMEM)
+ return r;
+ if (r < 0)
+ continue;
+ }
+
+ return 0;
+}
+
+static enum nss_status systemd_setent(GetentData *p) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ const char *name;
+ uid_t id;
+ int bypass, r;
+
+ BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
+ assert(p);
+
+ assert_se(pthread_mutex_lock(&p->mutex) == 0);
+
+ systemd_endent(p);
+
+ if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+ goto finish;
+
+ bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS");
+
+ if (bypass <= 0) {
+ r = sd_bus_open_system(&bus);
+ if (r < 0)
+ bypass = 1;
+ }
+
+ if (bypass > 0) {
+ r = direct_enumeration(p);
+ if (r < 0)
+ goto fail;
+
+ goto finish;
+ }
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetDynamicUsers",
+ &error,
+ &reply,
+ NULL);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_message_enter_container(reply, 'a', "(us)");
+ if (r < 0)
+ goto fail;
+
+ while ((r = sd_bus_message_read(reply, "(us)", &id, &name)) > 0) {
+ r = user_entry_add(p, name, id);
+ if (r == -ENOMEM)
+ goto fail;
+ if (r < 0)
+ continue;
+ }
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ goto fail;
+
+finish:
+ p->position = p->entries;
+ assert_se(pthread_mutex_unlock(&p->mutex) == 0);
+
+ return NSS_STATUS_SUCCESS;
+
+fail:
+ systemd_endent(p);
+ assert_se(pthread_mutex_unlock(&p->mutex) == 0);
+
+ return NSS_STATUS_UNAVAIL;
+}
+
+enum nss_status _nss_systemd_setpwent(int stayopen) {
+ return systemd_setent(&getpwent_data);
+}
+
+enum nss_status _nss_systemd_setgrent(int stayopen) {
+ return systemd_setent(&getgrent_data);
+}
+
+enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) {
+ enum nss_status ret;
+ UserEntry *p;
+ size_t len;
+
+ BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
+ assert(result);
+ assert(buffer);
+ assert(errnop);
+
+ assert_se(pthread_mutex_lock(&getpwent_data.mutex) == 0);
+
+ LIST_FOREACH(entries, p, getpwent_data.position) {
+ len = strlen(p->name) + 1;
+ if (buflen < len) {
+ *errnop = ERANGE;
+ ret = NSS_STATUS_TRYAGAIN;
+ goto finalize;
+ }
+
+ memcpy(buffer, p->name, len);
+
+ result->pw_name = buffer;
+ result->pw_uid = p->id;
+ result->pw_gid = p->id;
+ result->pw_gecos = (char*) DYNAMIC_USER_GECOS;
+ result->pw_passwd = (char*) DYNAMIC_USER_PASSWD;
+ result->pw_dir = (char*) DYNAMIC_USER_DIR;
+ result->pw_shell = (char*) DYNAMIC_USER_SHELL;
+ break;
+ }
+ if (!p) {
+ *errnop = ENOENT;
+ ret = NSS_STATUS_NOTFOUND;
+ goto finalize;
+ }
+
+ /* On success, step to the next entry. */
+ p = p->entries_next;
+ ret = NSS_STATUS_SUCCESS;
+
+finalize:
+ /* Save position for the next call. */
+ getpwent_data.position = p;
+
+ assert_se(pthread_mutex_unlock(&getpwent_data.mutex) == 0);
+
+ return ret;
+}
+
+enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) {
+ enum nss_status ret;
+ UserEntry *p;
+ size_t len;
+
+ BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
+ assert(result);
+ assert(buffer);
+ assert(errnop);
+
+ assert_se(pthread_mutex_lock(&getgrent_data.mutex) == 0);
+
+ LIST_FOREACH(entries, p, getgrent_data.position) {
+ len = sizeof(char*) + strlen(p->name) + 1;
+ if (buflen < len) {
+ *errnop = ERANGE;
+ ret = NSS_STATUS_TRYAGAIN;
+ goto finalize;
+ }
+
+ memzero(buffer, sizeof(char*));
+ strcpy(buffer + sizeof(char*), p->name);
+
+ result->gr_name = buffer + sizeof(char*);
+ result->gr_gid = p->id;
+ result->gr_passwd = (char*) DYNAMIC_USER_PASSWD;
+ result->gr_mem = (char**) buffer;
+ break;
+ }
+ if (!p) {
+ *errnop = ENOENT;
+ ret = NSS_STATUS_NOTFOUND;
+ goto finalize;
+ }
+
+ /* On success, step to the next entry. */
+ p = p->entries_next;
+ ret = NSS_STATUS_SUCCESS;
+
+finalize:
+ /* Save position for the next call. */
+ getgrent_data.position = p;
+
+ assert_se(pthread_mutex_unlock(&getgrent_data.mutex) == 0);
+
+ return ret;
+}
diff --git a/src/nss-systemd/nss-systemd.sym b/src/nss-systemd/nss-systemd.sym
index e3fe56f684..ff63382b15 100644
--- a/src/nss-systemd/nss-systemd.sym
+++ b/src/nss-systemd/nss-systemd.sym
@@ -1,8 +1,6 @@
/***
SPDX-License-Identifier: LGPL-2.1+
- 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
@@ -13,7 +11,13 @@
global:
_nss_systemd_getpwnam_r;
_nss_systemd_getpwuid_r;
+ _nss_systemd_endpwent;
+ _nss_systemd_setpwent;
+ _nss_systemd_getpwent_r;
_nss_systemd_getgrnam_r;
_nss_systemd_getgrgid_r;
+ _nss_systemd_endgrent;
+ _nss_systemd_setgrent;
+ _nss_systemd_getgrent_r;
local: *;
};
diff --git a/src/partition/growfs.c b/src/partition/growfs.c
index 41b4e872be..d2053cd391 100644
--- a/src/partition/growfs.c
+++ b/src/partition/growfs.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/partition/makefs.c b/src/partition/makefs.c
index a957967dfe..8c2a783e9d 100644
--- a/src/partition/makefs.c
+++ b/src/partition/makefs.c
@@ -1,22 +1,5 @@
/***
SPDX-License-Identifier: LGPL-2.1+
-
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <fcntl.h>
diff --git a/src/path/path.c b/src/path/path.c
index 0f029c4ae6..7bd30f22d4 100644
--- a/src/path/path.c
+++ b/src/path/path.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
@@ -67,6 +49,7 @@ static const char* const path_table[_SD_PATH_MAX] = {
[SD_PATH_USER_TEMPLATES] = "user-templates",
[SD_PATH_USER_DESKTOP] = "user-desktop",
[SD_PATH_SEARCH_BINARIES] = "search-binaries",
+ [SD_PATH_SEARCH_BINARIES_DEFAULT] = "search-binaries-default",
[SD_PATH_SEARCH_LIBRARY_PRIVATE] = "search-library-private",
[SD_PATH_SEARCH_LIBRARY_ARCH] = "search-library-arch",
[SD_PATH_SEARCH_SHARED] = "search-shared",
@@ -193,7 +176,6 @@ int main(int argc, char* argv[]) {
} else
r = list_homes();
-
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/portable/meson.build b/src/portable/meson.build
new file mode 100644
index 0000000000..dc57163460
--- /dev/null
+++ b/src/portable/meson.build
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+systemd_portabled_sources = files('''
+ portable.c
+ portable.h
+ portabled-bus.c
+ portabled-image-bus.c
+ portabled-image-bus.h
+ portabled-image.c
+ portabled-image.h
+ portabled-operation.c
+ portabled-operation.h
+ portabled.c
+ portabled.h
+'''.split())
+
+if conf.get('ENABLE_PORTABLED') == 1
+ install_data('org.freedesktop.portable1.conf',
+ install_dir : dbuspolicydir)
+ install_data('org.freedesktop.portable1.service',
+ install_dir : dbussystemservicedir)
+ install_data('org.freedesktop.portable1.policy',
+ install_dir : polkitpolicydir)
+
+ install_data('profile/default/service.conf', install_dir : join_paths(profiledir, 'default'))
+ install_data('profile/nonetwork/service.conf', install_dir : join_paths(profiledir, 'nonetwork'))
+ install_data('profile/strict/service.conf', install_dir : join_paths(profiledir, 'strict'))
+ install_data('profile/trusted/service.conf', install_dir : join_paths(profiledir, 'trusted'))
+endif
diff --git a/src/portable/org.freedesktop.portable1.conf b/src/portable/org.freedesktop.portable1.conf
new file mode 100644
index 0000000000..4c20a886e6
--- /dev/null
+++ b/src/portable/org.freedesktop.portable1.conf
@@ -0,0 +1,117 @@
+<?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">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<busconfig>
+
+ <policy user="root">
+ <allow own="org.freedesktop.portable1"/>
+ <allow send_destination="org.freedesktop.portable1"/>
+ <allow receive_sender="org.freedesktop.portable1"/>
+ </policy>
+
+ <policy context="default">
+ <deny send_destination="org.freedesktop.portable1"/>
+
+ <!-- generic interfaces -->
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.DBus.Introspectable"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.DBus.Peer"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.DBus.Properties"
+ send_member="Get"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.DBus.Properties"
+ send_member="GetAll"/>
+
+ <!-- Manager object -->
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="GetImage"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="ListImages"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="GetImageOSRelease"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="GetImageUnitFiles"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="GetImageState"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="AttachImage"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="DetachImage"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="RemoveImage"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="MarkImageReadOnly"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="SetImageLimit"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Manager"
+ send_member="SetPoolLimit"/>
+
+ <!-- Image object -->
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="GetOSRelease"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="GetUnitFiles"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="GetImageState"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="Attach"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="Detach"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="Remove"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="MarkReadOnly"/>
+
+ <allow send_destination="org.freedesktop.portable1"
+ send_interface="org.freedesktop.portable1.Image"
+ send_member="SetLimit"/>
+
+ <allow receive_sender="org.freedesktop.portable1"/>
+ </policy>
+
+</busconfig>
diff --git a/src/portable/org.freedesktop.portable1.policy b/src/portable/org.freedesktop.portable1.policy
new file mode 100644
index 0000000000..50bb44c4a4
--- /dev/null
+++ b/src/portable/org.freedesktop.portable1.policy
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<policyconfig>
+
+ <vendor>The systemd Project</vendor>
+ <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+ <action id="org.freedesktop.portable1.inspect-images">
+ <description gettext-domain="systemd">Inspect a portable service image</description>
+ <message gettext-domain="systemd">Authentication is required to inspect a portable service image.</message>
+ <defaults>
+ <allow_any>auth_admin</allow_any>
+ <allow_inactive>auth_admin</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.portable1.attach-images">
+ <description gettext-domain="systemd">Attach or detach a portable service image</description>
+ <message gettext-domain="systemd">Authentication is required to attach or detach a portable service image.</message>
+ <defaults>
+ <allow_any>auth_admin</allow_any>
+ <allow_inactive>auth_admin</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.systemd1.reload-daemon</annotate>
+ </action>
+
+ <action id="org.freedesktop.portable1.manage-images">
+ <description gettext-domain="systemd">Delete or modify portable service image</description>
+ <message gettext-domain="systemd">Authentication is required to delete or modify a portable service image.</message>
+ <defaults>
+ <allow_any>auth_admin</allow_any>
+ <allow_inactive>auth_admin</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+</policyconfig>
diff --git a/src/portable/org.freedesktop.portable1.service b/src/portable/org.freedesktop.portable1.service
new file mode 100644
index 0000000000..eff37b0183
--- /dev/null
+++ b/src/portable/org.freedesktop.portable1.service
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+[D-BUS Service]
+Name=org.freedesktop.portable1
+Exec=/bin/false
+User=root
+SystemdService=dbus-org.freedesktop.portable1.service
diff --git a/src/portable/portable.c b/src/portable/portable.c
new file mode 100644
index 0000000000..eb5daf3b0e
--- /dev/null
+++ b/src/portable/portable.c
@@ -0,0 +1,1427 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdio_ext.h>
+
+#include "bus-common-errors.h"
+#include "bus-error.h"
+#include "conf-files.h"
+#include "copy.h"
+#include "def.h"
+#include "dirent-util.h"
+#include "dissect-image.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "io-util.h"
+#include "locale-util.h"
+#include "loop-util.h"
+#include "machine-image.h"
+#include "mkdir.h"
+#include "os-util.h"
+#include "path-lookup.h"
+#include "portable.h"
+#include "process-util.h"
+#include "set.h"
+#include "signal-util.h"
+#include "socket-util.h"
+#include "string-table.h"
+#include "strv.h"
+#include "user-util.h"
+
+static const char profile_dirs[] = CONF_PATHS_NULSTR("systemd/portable/profile");
+
+/* Markers used in the first line of our 20-portable.conf unit file drop-in to determine, that a) the unit file was
+ * dropped there by the portable service logic and b) for which image it was dropped there. */
+#define PORTABLE_DROPIN_MARKER_BEGIN "# Drop-in created for image '"
+#define PORTABLE_DROPIN_MARKER_END "', do not edit."
+
+static bool prefix_match(const char *unit, const char *prefix) {
+ const char *p;
+
+ p = startswith(unit, prefix);
+ if (!p)
+ return false;
+
+ /* Only respect prefixes followed by dash or dot or when there's a complete match */
+ return IN_SET(*p, '-', '.', '@', 0);
+}
+
+static bool unit_match(const char *unit, char **matches) {
+ const char *dot;
+ char **i;
+
+ dot = strrchr(unit, '.');
+ if (!dot)
+ return false;
+
+ if (!STR_IN_SET(dot, ".service", ".socket", ".target", ".timer", ".path"))
+ return false;
+
+ /* Empty match expression means: everything */
+ if (strv_isempty(matches))
+ return true;
+
+ /* Otherwise, at least one needs to match */
+ STRV_FOREACH(i, matches)
+ if (prefix_match(unit, *i))
+ return true;
+
+ return false;
+}
+
+static PortableMetadata *portable_metadata_new(const char *name, int fd) {
+ PortableMetadata *m;
+
+ m = malloc0(offsetof(PortableMetadata, name) + strlen(name) + 1);
+ if (!m)
+ return NULL;
+
+ strcpy(m->name, name);
+ m->fd = fd;
+
+ return m;
+}
+
+PortableMetadata *portable_metadata_unref(PortableMetadata *i) {
+ if (!i)
+ return NULL;
+
+ safe_close(i->fd);
+ free(i->source);
+
+ return mfree(i);
+}
+
+Hashmap *portable_metadata_hashmap_unref(Hashmap *h) {
+
+ for (;;) {
+ PortableMetadata *i;
+
+ i = hashmap_steal_first(h);
+ if (!i)
+ break;
+
+ portable_metadata_unref(i);
+ }
+
+ return hashmap_free(h);
+}
+
+static int compare_metadata(PortableMetadata *const *x, PortableMetadata *const *y) {
+ return strcmp((*x)->name, (*y)->name);
+}
+
+int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetadata ***ret) {
+
+ _cleanup_free_ PortableMetadata **sorted = NULL;
+ Iterator iterator;
+ PortableMetadata *item;
+ size_t k = 0;
+
+ sorted = new(PortableMetadata*, hashmap_size(unit_files));
+ if (!sorted)
+ return -ENOMEM;
+
+ HASHMAP_FOREACH(item, unit_files, iterator)
+ sorted[k++] = item;
+
+ assert(k == hashmap_size(unit_files));
+
+ typesafe_qsort(sorted, k, compare_metadata);
+
+ *ret = TAKE_PTR(sorted);
+ return 0;
+}
+
+static int send_item(
+ int socket_fd,
+ const char *name,
+ int fd) {
+
+ union {
+ struct cmsghdr cmsghdr;
+ uint8_t buf[CMSG_SPACE(sizeof(int))];
+ } control = {};
+ struct iovec iovec;
+ struct msghdr mh = {
+ .msg_control = &control,
+ .msg_controllen = sizeof(control),
+ .msg_iov = &iovec,
+ .msg_iovlen = 1,
+ };
+ struct cmsghdr *cmsg;
+ _cleanup_close_ int data_fd = -1;
+
+ assert(socket_fd >= 0);
+ assert(name);
+ assert(fd >= 0);
+
+ data_fd = fd_duplicate_data_fd(fd);
+ if (data_fd < 0)
+ return data_fd;
+
+ cmsg = CMSG_FIRSTHDR(&mh);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ memcpy(CMSG_DATA(cmsg), &data_fd, sizeof(int));
+
+ mh.msg_controllen = CMSG_SPACE(sizeof(int));
+ iovec = IOVEC_MAKE_STRING(name);
+
+ if (sendmsg(socket_fd, &mh, MSG_NOSIGNAL) < 0)
+ return -errno;
+
+ return 0;
+}
+
+static int recv_item(
+ int socket_fd,
+ char **ret_name,
+ int *ret_fd) {
+
+ union {
+ struct cmsghdr cmsghdr;
+ uint8_t buf[CMSG_SPACE(sizeof(int))];
+ } control = {};
+ char buffer[PATH_MAX+2];
+ struct iovec iov = IOVEC_INIT(buffer, sizeof(buffer)-1);
+ struct msghdr mh = {
+ .msg_control = &control,
+ .msg_controllen = sizeof(control),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+ struct cmsghdr *cmsg;
+ _cleanup_close_ int found_fd = -1;
+ char *copy;
+ ssize_t n;
+
+ assert(socket_fd >= 0);
+ assert(ret_name);
+ assert(ret_fd);
+
+ n = recvmsg(socket_fd, &mh, MSG_CMSG_CLOEXEC);
+ if (n < 0)
+ return -errno;
+
+ CMSG_FOREACH(cmsg, &mh) {
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_RIGHTS) {
+
+ if (cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
+ assert(found_fd < 0);
+ found_fd = *(int*) CMSG_DATA(cmsg);
+ break;
+ }
+
+ cmsg_close_all(&mh);
+ return -EIO;
+ }
+ }
+
+ buffer[n] = 0;
+
+ copy = strdup(buffer);
+ if (!copy)
+ return -ENOMEM;
+
+ *ret_name = copy;
+ *ret_fd = TAKE_FD(found_fd);
+
+ return 0;
+}
+
+static int extract_now(
+ const char *where,
+ char **matches,
+ int socket_fd,
+ PortableMetadata **ret_os_release,
+ Hashmap **ret_unit_files) {
+
+ _cleanup_(portable_metadata_hashmap_unrefp) Hashmap *unit_files = NULL;
+ _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
+ _cleanup_close_ int os_release_fd = -1;
+ _cleanup_free_ char *os_release_path = NULL;
+ char **i;
+ int r;
+
+ /* Extracts the metadata from a directory tree 'where'. Extracts two kinds of information: the /etc/os-release
+ * data, and all unit files matching the specified expression. Note that this function is called in two very
+ * different but also similar contexts. When the tool gets invoked on a directory tree, we'll process it
+ * directly, and in-process, and thus can return the requested data directly, via 'ret_os_release' and
+ * 'ret_unit_files'. However, if the tool is invoked on a raw disk image — which needs to be mounted first — we
+ * are invoked in a child process with private mounts and then need to send the collected data to our
+ * parent. To handle both cases in one call this function also gets a 'socket_fd' parameter, which when >= 0 is
+ * used to send the data to the parent. */
+
+ assert(where);
+
+ /* First, find /etc/os-release and send it upstream (or just save it). */
+ r = open_os_release(where, &os_release_path, &os_release_fd);
+ if (r < 0)
+ log_debug_errno(r, "Couldn't acquire os-release file, ignoring: %m");
+ else {
+ if (socket_fd >= 0) {
+ r = send_item(socket_fd, "/etc/os-release", os_release_fd);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to send os-release file: %m");
+ }
+
+ if (ret_os_release) {
+ os_release = portable_metadata_new("/etc/os-release", os_release_fd);
+ if (!os_release)
+ return -ENOMEM;
+
+ os_release_fd = -1;
+ os_release->source = TAKE_PTR(os_release_path);
+ }
+ }
+
+ /* Then, send unit file data to the parent (or/and add it to the hashmap). For that we use our usual unit
+ * discovery logic. Note that we force looking inside of /lib/systemd/system/ for units too, as we mightbe
+ * compiled for a split-usr system but the image might be a legacy-usr one. */
+ r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, where);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to acquire lookup paths: %m");
+
+ unit_files = hashmap_new(&string_hash_ops);
+ if (!unit_files)
+ return -ENOMEM;
+
+ STRV_FOREACH(i, paths.search_path) {
+ _cleanup_free_ char *resolved = NULL;
+ _cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
+
+ r = chase_symlinks_and_opendir(*i, where, 0, &resolved, &d);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to open unit path '%s', ignoring: %m", *i);
+ continue;
+ }
+
+ FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to read directory: %m")) {
+ _cleanup_(portable_metadata_unrefp) PortableMetadata *m = NULL;
+ _cleanup_close_ int fd = -1;
+
+ if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
+ continue;
+
+ if (!unit_match(de->d_name, matches))
+ continue;
+
+ /* Filter out duplicates */
+ if (hashmap_get(unit_files, de->d_name))
+ continue;
+
+ dirent_ensure_type(d, de);
+ if (!IN_SET(de->d_type, DT_LNK, DT_REG))
+ continue;
+
+ fd = openat(dirfd(d), de->d_name, O_CLOEXEC|O_RDONLY);
+ if (fd < 0) {
+ log_debug_errno(errno, "Failed to open unit file '%s', ignoring: %m", de->d_name);
+ continue;
+ }
+
+ if (socket_fd >= 0) {
+ r = send_item(socket_fd, de->d_name, fd);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to send unit metadata to parent: %m");
+ }
+
+ m = portable_metadata_new(de->d_name, fd);
+ if (!m)
+ return -ENOMEM;
+ fd = -1;
+
+ m->source = strjoin(resolved, "/", de->d_name);
+ if (!m->source)
+ return -ENOMEM;
+
+ r = hashmap_put(unit_files, m->name, m);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to add unit to hashmap: %m");
+ m = NULL;
+ }
+ }
+
+ if (ret_os_release)
+ *ret_os_release = TAKE_PTR(os_release);
+ if (ret_unit_files)
+ *ret_unit_files = TAKE_PTR(unit_files);
+
+ return 0;
+}
+
+static int portable_extract_by_path(
+ const char *path,
+ char **matches,
+ PortableMetadata **ret_os_release,
+ Hashmap **ret_unit_files,
+ sd_bus_error *error) {
+
+ _cleanup_(portable_metadata_hashmap_unrefp) Hashmap *unit_files = NULL;
+ _cleanup_(portable_metadata_unrefp) PortableMetadata* os_release = NULL;
+ _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
+ int r;
+
+ assert(path);
+
+ r = loop_device_make_by_path(path, O_RDONLY, &d);
+ if (r == -EISDIR) {
+ /* We can't turn this into a loop-back block device, and this returns EISDIR? Then this is a directory
+ * tree and not a raw device. It's easy then. */
+
+ r = extract_now(path, matches, -1, &os_release, &unit_files);
+ if (r < 0)
+ return r;
+
+ } else if (r < 0)
+ return log_debug_errno(r, "Failed to set up loopback device: %m");
+ else {
+ _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
+ _cleanup_(rmdir_and_freep) char *tmpdir = NULL;
+ _cleanup_(close_pairp) int seq[2] = { -1, -1 };
+ _cleanup_(sigkill_waitp) pid_t child = 0;
+
+ /* We now have a loopback block device, let's fork off a child in its own mount namespace, mount it
+ * there, and extract the metadata we need. The metadata is sent from the child back to us. */
+
+ BLOCK_SIGNALS(SIGCHLD);
+
+ r = mkdtemp_malloc("/tmp/inspect-XXXXXX", &tmpdir);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to create temporary directory: %m");
+
+ r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP, &m);
+ if (r == -ENOPKG)
+ sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't identify a suitable partition table or file system in '%s'.", path);
+ else if (r == -EADDRNOTAVAIL)
+ sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "No root partition for specified root hash found in '%s'.", path);
+ else if (r == -ENOTUNIQ)
+ sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Multiple suitable root partitions found in image '%s'.", path);
+ else if (r == -ENXIO)
+ sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "No suitable root partition found in image '%s'.", path);
+ else if (r == -EPROTONOSUPPORT)
+ sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device '%s' is loopback block device with partition scanning turned off, please turn it on.", path);
+ if (r < 0)
+ return r;
+
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, seq) < 0)
+ return log_debug_errno(errno, "Failed to allocated SOCK_SEQPACKET socket: %m");
+
+ r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ seq[0] = safe_close(seq[0]);
+
+ r = dissected_image_mount(m, tmpdir, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_VALIDATE_OS);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to mount dissected image: %m");
+ goto child_finish;
+ }
+
+ r = extract_now(tmpdir, matches, seq[1], NULL, NULL);
+
+ child_finish:
+ _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+ }
+
+ seq[1] = safe_close(seq[1]);
+
+ unit_files = hashmap_new(&string_hash_ops);
+ if (!unit_files)
+ return -ENOMEM;
+
+ for (;;) {
+ _cleanup_(portable_metadata_unrefp) PortableMetadata *add = NULL;
+ _cleanup_free_ char *name = NULL;
+ _cleanup_close_ int fd = -1;
+
+ r = recv_item(seq[0], &name, &fd);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to receive item: %m");
+
+ /* We can't really distuingish a zero-length datagram without any fds from EOF (both are signalled the
+ * same way by recvmsg()). Hence, accept either as end notification. */
+ if (isempty(name) && fd < 0)
+ break;
+
+ if (isempty(name) || fd < 0) {
+ log_debug("Invalid item sent from child.");
+ return -EINVAL;
+ }
+
+ add = portable_metadata_new(name, fd);
+ if (!add)
+ return -ENOMEM;
+ fd = -1;
+
+ /* Note that we do not initialize 'add->source' here, as the source path is not usable here as
+ * it refers to a path only valid in the short-living namespaced child process we forked
+ * here. */
+
+ if (PORTABLE_METADATA_IS_UNIT(add)) {
+ r = hashmap_put(unit_files, add->name, add);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to add item to unit file list: %m");
+
+ add = NULL;
+
+ } else if (PORTABLE_METADATA_IS_OS_RELEASE(add)) {
+
+ assert(!os_release);
+ os_release = TAKE_PTR(add);
+ } else
+ assert_not_reached("Unexpected metadata item from child.");
+ }
+
+ r = wait_for_terminate_and_check("(sd-dissect)", child, 0);
+ if (r < 0)
+ return r;
+ child = 0;
+ }
+
+ if (!os_release)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image '%s' lacks os-release data, refusing.", path);
+
+ if (hashmap_isempty(unit_files))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't find any matching unit files in image '%s', refusing.", path);
+
+ if (ret_unit_files)
+ *ret_unit_files = TAKE_PTR(unit_files);
+
+ if (ret_os_release)
+ *ret_os_release = TAKE_PTR(os_release);
+
+ return 0;
+}
+
+int portable_extract(
+ const char *name_or_path,
+ char **matches,
+ PortableMetadata **ret_os_release,
+ Hashmap **ret_unit_files,
+ sd_bus_error *error) {
+
+ _cleanup_(image_unrefp) Image *image = NULL;
+ int r;
+
+ assert(name_or_path);
+
+ r = image_find_harder(IMAGE_PORTABLE, name_or_path, &image);
+ if (r < 0)
+ return r;
+
+ return portable_extract_by_path(image->path, matches, ret_os_release, ret_unit_files, error);
+}
+
+static int unit_file_is_active(
+ sd_bus *bus,
+ const char *name,
+ sd_bus_error *error) {
+
+ static const char *const active_states[] = {
+ "activating",
+ "active",
+ "reloading",
+ "deactivating",
+ NULL,
+ };
+ int r;
+
+ if (!bus)
+ return false;
+
+ /* If we are looking at a plain or instance things are easy, we can just query the state */
+ if (unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
+ _cleanup_free_ char *path = NULL, *buf = NULL;
+
+ path = unit_dbus_path_from_name(name);
+ if (!path)
+ return -ENOMEM;
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.systemd1.Unit",
+ "ActiveState",
+ error,
+ &buf);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to retrieve unit state: %s", bus_error_message(error, r));
+
+ return strv_contains((char**) active_states, buf);
+ }
+
+ /* Otherwise we need to enumerate. But let's build the most restricted query we can */
+ if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+ const char *at, *prefix, *joined;
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "ListUnitsByPatterns");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append_strv(m, (char**) active_states);
+ if (r < 0)
+ return r;
+
+ at = strchr(name, '@');
+ assert(at);
+
+ prefix = strndupa(name, at + 1 - name);
+ joined = strjoina(prefix, "*", at + 1);
+
+ r = sd_bus_message_append_strv(m, STRV_MAKE(joined));
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call(bus, m, 0, error, &reply);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to list units: %s", bus_error_message(error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_STRUCT, "ssssssouso");
+ if (r < 0)
+ return r;
+
+ return r > 0;
+ }
+
+ return -EINVAL;
+}
+
+static int portable_changes_add(
+ PortableChange **changes,
+ size_t *n_changes,
+ PortableChangeType type,
+ const char *path,
+ const char *source) {
+
+ _cleanup_free_ char *p = NULL, *s = NULL;
+ PortableChange *c;
+
+ assert(path);
+ assert(!changes == !n_changes);
+
+ if (!changes)
+ return 0;
+
+ c = reallocarray(*changes, *n_changes + 1, sizeof(PortableChange));
+ if (!c)
+ return -ENOMEM;
+ *changes = c;
+
+ p = strdup(path);
+ if (!p)
+ return -ENOMEM;
+
+ path_simplify(p, false);
+
+ if (source) {
+ s = strdup(source);
+ if (!s)
+ return -ENOMEM;
+
+ path_simplify(s, false);
+ }
+
+ c[(*n_changes)++] = (PortableChange) {
+ .type = type,
+ .path = TAKE_PTR(p),
+ .source = TAKE_PTR(s),
+ };
+
+ return 0;
+}
+
+static int portable_changes_add_with_prefix(
+ PortableChange **changes,
+ size_t *n_changes,
+ PortableChangeType type,
+ const char *prefix,
+ const char *path,
+ const char *source) {
+
+ assert(path);
+ assert(!changes == !n_changes);
+
+ if (!changes)
+ return 0;
+
+ if (prefix) {
+ path = strjoina(prefix, "/", path);
+
+ if (source)
+ source = strjoina(prefix, "/", source);
+ }
+
+ return portable_changes_add(changes, n_changes, type, path, source);
+}
+
+void portable_changes_free(PortableChange *changes, size_t n_changes) {
+ size_t i;
+
+ assert(changes || n_changes == 0);
+
+ for (i = 0; i < n_changes; i++) {
+ free(changes[i].path);
+ free(changes[i].source);
+ }
+
+ free(changes);
+}
+
+static int install_chroot_dropin(
+ const char *image_path,
+ ImageType type,
+ const PortableMetadata *m,
+ const char *dropin_dir,
+ char **ret_dropin,
+ PortableChange **changes,
+ size_t *n_changes) {
+
+ _cleanup_free_ char *text = NULL, *dropin = NULL;
+ int r;
+
+ assert(image_path);
+ assert(m);
+ assert(dropin_dir);
+
+ dropin = strjoin(dropin_dir, "/20-portable.conf");
+ if (!dropin)
+ return -ENOMEM;
+
+ text = strjoin(PORTABLE_DROPIN_MARKER_BEGIN, image_path, PORTABLE_DROPIN_MARKER_END "\n");
+ if (!text)
+ return -ENOMEM;
+
+ if (endswith(m->name, ".service"))
+ if (!strextend(&text,
+ "\n"
+ "[Service]\n",
+ IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "RootDirectory=" : "RootImage=", image_path, "\n"
+ "Environment=PORTABLE=", basename(image_path), "\n"
+ "LogExtraFields=PORTABLE=", basename(image_path), "\n",
+ NULL))
+
+ return -ENOMEM;
+
+ r = write_string_file(dropin, text, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to write '%s': %m", dropin);
+
+ (void) portable_changes_add(changes, n_changes, PORTABLE_WRITE, dropin, NULL);
+
+ if (ret_dropin)
+ *ret_dropin = TAKE_PTR(dropin);
+
+ return 0;
+}
+
+static int find_profile(const char *name, const char *unit, char **ret) {
+ const char *p, *dot;
+
+ assert(name);
+ assert(ret);
+
+ assert_se(dot = strrchr(unit, '.'));
+
+ NULSTR_FOREACH(p, profile_dirs) {
+ _cleanup_free_ char *joined;
+
+ joined = strjoin(p, "/", name, "/", dot + 1, ".conf");
+ if (!joined)
+ return -ENOMEM;
+
+ if (laccess(joined, F_OK) >= 0) {
+ *ret = TAKE_PTR(joined);
+ return 0;
+ }
+
+ if (errno != ENOENT)
+ return -errno;
+ }
+
+ return -ENOENT;
+}
+
+static int install_profile_dropin(
+ const char *image_path,
+ const PortableMetadata *m,
+ const char *dropin_dir,
+ const char *profile,
+ PortableFlags flags,
+ char **ret_dropin,
+ PortableChange **changes,
+ size_t *n_changes) {
+
+ _cleanup_free_ char *dropin = NULL, *from = NULL;
+ int r;
+
+ assert(image_path);
+ assert(m);
+ assert(dropin_dir);
+
+ if (!profile)
+ return 0;
+
+ r = find_profile(profile, m->name, &from);
+ if (r < 0) {
+ if (r != ENOENT)
+ return log_debug_errno(errno, "Profile '%s' is not accessible: %m", profile);
+
+ log_debug_errno(errno, "Skipping link to profile '%s', as it does not exist: %m", profile);
+ return 0;
+ }
+
+ dropin = strjoin(dropin_dir, "/10-profile.conf");
+ if (!dropin)
+ return -ENOMEM;
+
+ if (flags & PORTABLE_PREFER_COPY) {
+
+ r = copy_file_atomic(from, dropin, 0644, 0, COPY_REFLINK);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to copy %s %s %s: %m", from, special_glyph(ARROW), dropin);
+
+ (void) portable_changes_add(changes, n_changes, PORTABLE_COPY, dropin, from);
+
+ } else {
+
+ if (symlink(from, dropin) < 0)
+ return log_debug_errno(errno, "Failed to link %s %s %s: %m", from, special_glyph(ARROW), dropin);
+
+ (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, dropin, from);
+ }
+
+ if (ret_dropin)
+ *ret_dropin = TAKE_PTR(dropin);
+
+ return 0;
+}
+
+static const char *config_path(const LookupPaths *paths, PortableFlags flags) {
+ const char *where;
+
+ assert(paths);
+
+ if (flags & PORTABLE_RUNTIME)
+ where = paths->runtime_config;
+ else
+ where = paths->persistent_config;
+
+ assert(where);
+ return where;
+}
+
+static int attach_unit_file(
+ const LookupPaths *paths,
+ const char *image_path,
+ ImageType type,
+ const PortableMetadata *m,
+ const char *profile,
+ PortableFlags flags,
+ PortableChange **changes,
+ size_t *n_changes) {
+
+ _cleanup_(unlink_and_freep) char *chroot_dropin = NULL, *profile_dropin = NULL;
+ _cleanup_(rmdir_and_freep) char *dropin_dir = NULL;
+ const char *where, *path;
+ int r;
+
+ assert(paths);
+ assert(image_path);
+ assert(m);
+ assert(PORTABLE_METADATA_IS_UNIT(m));
+
+ where = config_path(paths, flags);
+ path = strjoina(where, "/", m->name);
+
+ dropin_dir = strjoin(path, ".d");
+ if (!dropin_dir)
+ return -ENOMEM;
+
+ (void) mkdir_p(dropin_dir, 0755);
+ (void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, dropin_dir, NULL);
+
+ /* We install the drop-ins first, and the actual unit file last to achieve somewhat atomic behaviour if PID 1
+ * is reloaded while we are creating things here: as long as only the drop-ins exist the unit doesn't exist at
+ * all for PID 1. */
+
+ r = install_chroot_dropin(image_path, type, m, dropin_dir, &chroot_dropin, changes, n_changes);
+ if (r < 0)
+ return r;
+
+ r = install_profile_dropin(image_path, m, dropin_dir, profile, flags, &profile_dropin, changes, n_changes);
+ if (r < 0)
+ return r;
+
+ if ((flags & PORTABLE_PREFER_SYMLINK) && m->source) {
+
+ if (symlink(m->source, path) < 0)
+ return log_debug_errno(errno, "Failed to symlink unit file '%s': %m", path);
+
+ (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, path, m->source);
+
+ } else {
+ _cleanup_(unlink_and_freep) char *tmp = NULL;
+ _cleanup_close_ int fd = -1;
+
+ fd = open_tmpfile_linkable(where, O_WRONLY|O_CLOEXEC, &tmp);
+ if (fd < 0)
+ return log_debug_errno(fd, "Failed to create unit file '%s': %m", path);
+
+ r = copy_bytes(m->fd, fd, UINT64_MAX, COPY_REFLINK);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to copy unit file '%s': %m", path);
+
+ if (fchmod(fd, 0644) < 0)
+ return log_debug_errno(errno, "Failed to change unit file access mode for '%s': %m", path);
+
+ r = link_tmpfile(fd, tmp, path);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to install unit file '%s': %m", path);
+
+ tmp = mfree(tmp);
+
+ (void) portable_changes_add(changes, n_changes, PORTABLE_COPY, path, m->source);
+ }
+
+ /* All is established now, now let's disable any rollbacks */
+ chroot_dropin = mfree(chroot_dropin);
+ profile_dropin = mfree(profile_dropin);
+ dropin_dir = mfree(dropin_dir);
+
+ return 0;
+}
+
+static int image_symlink(
+ const char *image_path,
+ PortableFlags flags,
+ char **ret) {
+
+ const char *fn, *where;
+ char *joined = NULL;
+
+ assert(image_path);
+ assert(ret);
+
+ fn = last_path_component(image_path);
+
+ if (flags & PORTABLE_RUNTIME)
+ where = "/run/portables/";
+ else
+ where = "/etc/portables/";
+
+ joined = strjoin(where, fn);
+ if (!joined)
+ return -ENOMEM;
+
+ *ret = joined;
+ return 0;
+}
+
+static int install_image_symlink(
+ const char *image_path,
+ PortableFlags flags,
+ PortableChange **changes,
+ size_t *n_changes) {
+
+ _cleanup_free_ char *sl = NULL;
+ int r;
+
+ assert(image_path);
+
+ /* If the image is outside of the image search also link it into it, so that it can be found with short image
+ * names and is listed among the images. */
+
+ if (image_in_search_path(IMAGE_PORTABLE, image_path))
+ return 0;
+
+ r = image_symlink(image_path, flags, &sl);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to generate image symlink path: %m");
+
+ (void) mkdir_parents(sl, 0755);
+
+ if (symlink(image_path, sl) < 0)
+ return log_debug_errno(errno, "Failed to link %s %s %s: %m", image_path, special_glyph(ARROW), sl);
+
+ (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, sl, image_path);
+ return 0;
+}
+
+int portable_attach(
+ sd_bus *bus,
+ const char *name_or_path,
+ char **matches,
+ const char *profile,
+ PortableFlags flags,
+ PortableChange **changes,
+ size_t *n_changes,
+ sd_bus_error *error) {
+
+ _cleanup_(portable_metadata_hashmap_unrefp) Hashmap *unit_files = NULL;
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
+ _cleanup_(image_unrefp) Image *image = NULL;
+ PortableMetadata *item;
+ Iterator iterator;
+ int r;
+
+ assert(name_or_path);
+
+ r = image_find_harder(IMAGE_PORTABLE, name_or_path, &image);
+ if (r < 0)
+ return r;
+
+ r = portable_extract_by_path(image->path, matches, NULL, &unit_files, error);
+ if (r < 0)
+ return r;
+
+ r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL);
+ if (r < 0)
+ return r;
+
+ HASHMAP_FOREACH(item, unit_files, iterator) {
+ r = unit_file_exists(UNIT_FILE_SYSTEM, &paths, item->name);
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name);
+ if (r > 0)
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' exists on the host already, refusing.", item->name);
+
+ r = unit_file_is_active(bus, item->name, error);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active already, refusing.", item->name);
+ }
+
+ HASHMAP_FOREACH(item, unit_files, iterator) {
+ r = attach_unit_file(&paths, image->path, image->type, item, profile, flags, changes, n_changes);
+ if (r < 0)
+ return r;
+ }
+
+ /* We don't care too much for the image symlink, it's just a convenience thing, it's not necessary for proper
+ * operation otherwise. */
+ (void) install_image_symlink(image->path, flags, changes, n_changes);
+
+ return 0;
+}
+
+static bool marker_matches_image(const char *marker, const char *name_or_path) {
+ const char *a;
+
+ assert(marker);
+ assert(name_or_path);
+
+ a = last_path_component(marker);
+
+ if (image_name_is_valid(name_or_path)) {
+ const char *e;
+
+ /* We shall match against an image name. In that case let's compare the last component, and optionally
+ * allow either a suffix of ".raw" or a series of "/". */
+
+ e = startswith(a, name_or_path);
+ if (!e)
+ return false;
+
+ return
+ e[strspn(e, "/")] == 0 ||
+ streq(e, ".raw");
+ } else {
+ const char *b;
+ size_t l;
+
+ /* We shall match against a path. Let's ignore any prefix here though, as often there are many ways to
+ * reach the same file. However, in this mode, let's validate any file suffix. */
+
+ l = strcspn(a, "/");
+ b = last_path_component(name_or_path);
+
+ if (strcspn(b, "/") != l)
+ return false;
+
+ return memcmp(a, b, l) == 0;
+ }
+}
+
+static int test_chroot_dropin(
+ DIR *d,
+ const char *where,
+ const char *fname,
+ const char *name_or_path,
+ char **ret_marker) {
+
+ _cleanup_free_ char *line = NULL, *marker = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_close_ int fd = -1;
+ const char *p, *e, *k;
+ int r;
+
+ assert(d);
+ assert(where);
+ assert(fname);
+
+ /* We recognize unis created from portable images via the drop-in we created for them */
+
+ p = strjoina(fname, ".d/20-portable.conf");
+ fd = openat(dirfd(d), p, O_RDONLY|O_CLOEXEC);
+ if (fd < 0) {
+ if (errno == ENOENT)
+ return 0;
+
+ return log_debug_errno(errno, "Failed to open %s/%s: %m", where, p);
+ }
+
+ f = fdopen(fd, "re");
+ if (!f)
+ return log_debug_errno(errno, "Failed to convert file handle: %m");
+ fd = -1;
+
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to read from %s/%s: %m", where, p);
+
+ e = startswith(line, PORTABLE_DROPIN_MARKER_BEGIN);
+ if (!e)
+ return 0;
+
+ k = endswith(e, PORTABLE_DROPIN_MARKER_END);
+ if (!k)
+ return 0;
+
+ marker = strndup(e, k - e);
+ if (!marker)
+ return -ENOMEM;
+
+ if (!name_or_path)
+ r = true;
+ else
+ r = marker_matches_image(marker, name_or_path);
+
+ if (ret_marker)
+ *ret_marker = TAKE_PTR(marker);
+
+ return r;
+}
+
+int portable_detach(
+ sd_bus *bus,
+ const char *name_or_path,
+ PortableFlags flags,
+ PortableChange **changes,
+ size_t *n_changes,
+ sd_bus_error *error) {
+
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
+ _cleanup_set_free_free_ Set *unit_files = NULL, *markers = NULL;
+ _cleanup_closedir_ DIR *d = NULL;
+ const char *where, *item;
+ Iterator iterator;
+ struct dirent *de;
+ int ret = 0;
+ int r;
+
+ assert(name_or_path);
+
+ r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL);
+ if (r < 0)
+ return r;
+
+ where = config_path(&paths, flags);
+
+ d = opendir(where);
+ if (!d)
+ return log_debug_errno(errno, "Failed to open '%s' directory: %m", where);
+
+ unit_files = set_new(&string_hash_ops);
+ if (!unit_files)
+ return -ENOMEM;
+
+ markers = set_new(&path_hash_ops);
+ if (!markers)
+ return -ENOMEM;
+
+ FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to enumerate '%s' directory: %m", where)) {
+ _cleanup_free_ char *marker = NULL;
+ UnitFileState state;
+
+ if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
+ continue;
+
+ /* Filter out duplicates */
+ if (set_get(unit_files, de->d_name))
+ continue;
+
+ dirent_ensure_type(d, de);
+ if (!IN_SET(de->d_type, DT_LNK, DT_REG))
+ continue;
+
+ r = test_chroot_dropin(d, where, de->d_name, name_or_path, &marker);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
+
+ r = unit_file_lookup_state(UNIT_FILE_SYSTEM, &paths, de->d_name, &state);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to determine unit file state of '%s': %m", de->d_name);
+ if (!IN_SET(state, UNIT_FILE_STATIC, UNIT_FILE_DISABLED, UNIT_FILE_LINKED, UNIT_FILE_RUNTIME))
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is in state '%s', can't detach.", de->d_name, unit_file_state_to_string(state));
+
+ r = unit_file_is_active(bus, de->d_name, error);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active, can't detach.", de->d_name);
+
+ r = set_put_strdup(unit_files, de->d_name);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to add unit name '%s' to set: %m", de->d_name);
+
+ if (path_is_absolute(marker) &&
+ !image_in_search_path(IMAGE_PORTABLE, marker)) {
+
+ r = set_ensure_allocated(&markers, &path_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = set_put(markers, marker);
+ if (r >= 0)
+ marker = NULL;
+ else if (r != -EEXIST)
+ return r;
+ }
+ }
+
+ if (set_isempty(unit_files)) {
+ log_debug("No unit files associated with '%s' found. Image not attached?", name_or_path);
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "No unit files associated with '%s' found. Image not attached?", name_or_path);
+ }
+
+ SET_FOREACH(item, unit_files, iterator) {
+ _cleanup_free_ char *md = NULL;
+ const char *suffix;
+
+ if (unlinkat(dirfd(d), item, 0) < 0) {
+ log_debug_errno(errno, "Can't remove unit file %s/%s: %m", where, item);
+
+ if (errno != ENOENT && ret >= 0)
+ ret = -errno;
+ } else
+ portable_changes_add_with_prefix(changes, n_changes, PORTABLE_UNLINK, where, item, NULL);
+
+ FOREACH_STRING(suffix, ".d/10-profile.conf", ".d/20-portable.conf") {
+ _cleanup_free_ char *dropin = NULL;
+
+ dropin = strjoin(item, suffix);
+ if (!dropin)
+ return -ENOMEM;
+
+ if (unlinkat(dirfd(d), dropin, 0) < 0) {
+ log_debug_errno(errno, "Can't remove drop-in %s/%s: %m", where, dropin);
+
+ if (errno != ENOENT && ret >= 0)
+ ret = -errno;
+ } else
+ portable_changes_add_with_prefix(changes, n_changes, PORTABLE_UNLINK, where, dropin, NULL);
+ }
+
+ md = strjoin(item, ".d");
+ if (!md)
+ return -ENOMEM;
+
+ if (unlinkat(dirfd(d), md, AT_REMOVEDIR) < 0) {
+ log_debug_errno(errno, "Can't remove drop-in directory %s/%s: %m", where, md);
+
+ if (errno != ENOENT && ret >= 0)
+ ret = -errno;
+ } else
+ portable_changes_add_with_prefix(changes, n_changes, PORTABLE_UNLINK, where, md, NULL);
+ }
+
+ /* Now, also drop any image symlink, for images outside of the sarch path */
+ SET_FOREACH(item, markers, iterator) {
+ _cleanup_free_ char *sl = NULL;
+ struct stat st;
+
+ r = image_symlink(item, flags, &sl);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine image symlink for '%s', ignoring: %m", item);
+ continue;
+ }
+
+ if (lstat(sl, &st) < 0) {
+ log_debug_errno(errno, "Failed to stat '%s', ignoring: %m", sl);
+ continue;
+ }
+
+ if (!S_ISLNK(st.st_mode)) {
+ log_debug("Image '%s' is not a symlink, ignoring.", sl);
+ continue;
+ }
+
+ if (unlink(sl) < 0) {
+ log_debug_errno(errno, "Can't remove image symlink '%s': %m", sl);
+
+ if (errno != ENOENT && ret >= 0)
+ ret = -errno;
+ } else
+ portable_changes_add(changes, n_changes, PORTABLE_UNLINK, sl, NULL);
+ }
+
+ return ret;
+}
+
+static int portable_get_state_internal(
+ sd_bus *bus,
+ const char *name_or_path,
+ PortableFlags flags,
+ PortableState *ret,
+ sd_bus_error *error) {
+
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
+ bool found_enabled = false, found_running = false;
+ _cleanup_set_free_free_ Set *unit_files = NULL;
+ _cleanup_closedir_ DIR *d = NULL;
+ const char *where;
+ struct dirent *de;
+ int r;
+
+ assert(name_or_path);
+ assert(ret);
+
+ r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL);
+ if (r < 0)
+ return r;
+
+ where = config_path(&paths, flags);
+
+ d = opendir(where);
+ if (!d)
+ return log_debug_errno(errno, "Failed to open '%s' directory: %m", where);
+
+ unit_files = set_new(&string_hash_ops);
+ if (!unit_files)
+ return -ENOMEM;
+
+ FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to enumerate '%s' directory: %m", where)) {
+ UnitFileState state;
+
+ if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
+ continue;
+
+ /* Filter out duplicates */
+ if (set_get(unit_files, de->d_name))
+ continue;
+
+ dirent_ensure_type(d, de);
+ if (!IN_SET(de->d_type, DT_LNK, DT_REG))
+ continue;
+
+ r = test_chroot_dropin(d, where, de->d_name, name_or_path, NULL);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
+
+ r = unit_file_lookup_state(UNIT_FILE_SYSTEM, &paths, de->d_name, &state);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to determine unit file state of '%s': %m", de->d_name);
+ if (!IN_SET(state, UNIT_FILE_STATIC, UNIT_FILE_DISABLED, UNIT_FILE_LINKED, UNIT_FILE_LINKED_RUNTIME))
+ found_enabled = true;
+
+ r = unit_file_is_active(bus, de->d_name, error);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ found_running = true;
+
+ r = set_put_strdup(unit_files, de->d_name);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to add unit name '%s' to set: %m", de->d_name);
+ }
+
+ *ret = found_running ? (!set_isempty(unit_files) && (flags & PORTABLE_RUNTIME) ? PORTABLE_RUNNING_RUNTIME : PORTABLE_RUNNING) :
+ found_enabled ? (flags & PORTABLE_RUNTIME ? PORTABLE_ENABLED_RUNTIME : PORTABLE_ENABLED) :
+ !set_isempty(unit_files) ? (flags & PORTABLE_RUNTIME ? PORTABLE_ATTACHED_RUNTIME : PORTABLE_ATTACHED) : PORTABLE_DETACHED;
+
+ return 0;
+}
+
+int portable_get_state(
+ sd_bus *bus,
+ const char *name_or_path,
+ PortableFlags flags,
+ PortableState *ret,
+ sd_bus_error *error) {
+
+ PortableState state;
+ int r;
+
+ assert(name_or_path);
+ assert(ret);
+
+ /* We look for matching units twice: once in the regular directories, and once in the runtime directories — but
+ * the latter only if we didn't find anything in the former. */
+
+ r = portable_get_state_internal(bus, name_or_path, flags & ~PORTABLE_RUNTIME, &state, error);
+ if (r < 0)
+ return r;
+
+ if (state == PORTABLE_DETACHED) {
+ r = portable_get_state_internal(bus, name_or_path, flags | PORTABLE_RUNTIME, &state, error);
+ if (r < 0)
+ return r;
+ }
+
+ *ret = state;
+ return 0;
+}
+
+int portable_get_profiles(char ***ret) {
+ assert(ret);
+
+ return conf_files_list_nulstr(ret, NULL, NULL, CONF_FILES_DIRECTORY|CONF_FILES_BASENAME|CONF_FILES_FILTER_MASKED, profile_dirs);
+}
+
+static const char* const portable_change_type_table[_PORTABLE_CHANGE_TYPE_MAX] = {
+ [PORTABLE_COPY] = "copy",
+ [PORTABLE_MKDIR] = "mkdir",
+ [PORTABLE_SYMLINK] = "symlink",
+ [PORTABLE_UNLINK] = "unlink",
+ [PORTABLE_WRITE] = "write",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(portable_change_type, PortableChangeType);
+
+static const char* const portable_state_table[_PORTABLE_STATE_MAX] = {
+ [PORTABLE_DETACHED] = "detached",
+ [PORTABLE_ATTACHED] = "attached",
+ [PORTABLE_ATTACHED_RUNTIME] = "attached-runtime",
+ [PORTABLE_ENABLED] = "enabled",
+ [PORTABLE_ENABLED_RUNTIME] = "enabled-runtime",
+ [PORTABLE_RUNNING] = "running",
+ [PORTABLE_RUNNING_RUNTIME] = "running-runtime",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(portable_state, PortableState);
diff --git a/src/portable/portable.h b/src/portable/portable.h
new file mode 100644
index 0000000000..9fbf61265a
--- /dev/null
+++ b/src/portable/portable.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-bus.h"
+
+#include "hashmap.h"
+#include "macro.h"
+#include "set.h"
+#include "string-util.h"
+
+typedef struct PortableMetadata {
+ int fd;
+ char *source;
+ char name[];
+} PortableMetadata;
+
+#define PORTABLE_METADATA_IS_OS_RELEASE(m) (streq((m)->name, "/etc/os-release"))
+#define PORTABLE_METADATA_IS_UNIT(m) (!IN_SET((m)->name[0], 0, '/'))
+
+typedef enum PortableFlags {
+ PORTABLE_PREFER_COPY = 1 << 0,
+ PORTABLE_PREFER_SYMLINK = 1 << 1,
+ PORTABLE_RUNTIME = 1 << 2,
+} PortableFlags;
+
+typedef enum PortableChangeType {
+ PORTABLE_COPY,
+ PORTABLE_SYMLINK,
+ PORTABLE_UNLINK,
+ PORTABLE_WRITE,
+ PORTABLE_MKDIR,
+ _PORTABLE_CHANGE_TYPE_MAX,
+ _PORTABLE_CHANGE_TYPE_INVALID = INT_MIN,
+} PortableChangeType;
+
+typedef enum PortableState {
+ PORTABLE_DETACHED,
+ PORTABLE_ATTACHED,
+ PORTABLE_ATTACHED_RUNTIME,
+ PORTABLE_ENABLED,
+ PORTABLE_ENABLED_RUNTIME,
+ PORTABLE_RUNNING,
+ PORTABLE_RUNNING_RUNTIME,
+ _PORTABLE_STATE_MAX,
+ _PORTABLE_STATE_INVALID = -1
+} PortableState;
+
+typedef struct PortableChange {
+ int type; /* PortableFileChangeType or negative error number */
+ char *path;
+ char *source;
+} PortableChange;
+
+PortableMetadata *portable_metadata_unref(PortableMetadata *i);
+DEFINE_TRIVIAL_CLEANUP_FUNC(PortableMetadata*, portable_metadata_unref);
+
+Hashmap *portable_metadata_hashmap_unref(Hashmap *h);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, portable_metadata_hashmap_unref);
+
+int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetadata ***ret);
+
+int portable_extract(const char *image, char **matches, PortableMetadata **ret_os_release, Hashmap **ret_unit_files, sd_bus_error *error);
+
+int portable_attach(sd_bus *bus, const char *name_or_path, char **matches, const char *profile, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error);
+int portable_detach(sd_bus *bus, const char *name_or_path, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error);
+
+int portable_get_state(sd_bus *bus, const char *name_or_path, PortableFlags flags, PortableState *ret, sd_bus_error *error);
+
+int portable_get_profiles(char ***ret);
+
+void portable_changes_free(PortableChange *changes, size_t n_changes);
+
+const char *portable_change_type_to_string(PortableChangeType t) _const_;
+PortableChangeType portable_change_type_from_string(const char *t) _pure_;
+
+const char *portable_state_to_string(PortableState t) _const_;
+PortableState portable_state_from_string(const char *t) _pure_;
diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c
new file mode 100644
index 0000000000..b4895e6380
--- /dev/null
+++ b/src/portable/portablectl.c
@@ -0,0 +1,968 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+#include <getopt.h>
+
+#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "def.h"
+#include "dirent-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "format-table.h"
+#include "fs-util.h"
+#include "locale-util.h"
+#include "machine-image.h"
+#include "pager.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "spawn-polkit-agent.h"
+#include "string-util.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "verbs.h"
+
+static bool arg_no_pager = false;
+static bool arg_legend = true;
+static bool arg_ask_password = true;
+static bool arg_quiet = false;
+static const char *arg_profile = "default";
+static const char* arg_copy_mode = NULL;
+static bool arg_runtime = false;
+static bool arg_reload = true;
+static bool arg_cat = false;
+static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
+static char *arg_host = NULL;
+
+static int determine_image(const char *image, bool permit_non_existing, char **ret) {
+ int r;
+
+ /* If the specified name is a valid image name, we pass it as-is to portabled, which will search for it in the
+ * usual search directories. Otherwise we presume it's a path, and will normalize it on the client's side
+ * (among other things, to make the path independent of the client's working directory) before passing it
+ * over. */
+
+ if (image_name_is_valid(image)) {
+ char *c;
+
+ if (!arg_quiet && laccess(image, F_OK) >= 0)
+ log_warning("Ambiguous invocation: current working directory contains file matching non-path argument '%s', ignoring. "
+ "Prefix argument with './' to force reference to file in current working directory.", image);
+
+ c = strdup(image);
+ if (!c)
+ return log_oom();
+
+ *ret = c;
+ return 0;
+ }
+
+ if (arg_transport != BUS_TRANSPORT_LOCAL) {
+ log_error("Operations on images by path not supported when connecting to remote systems.");
+ return -EOPNOTSUPP;
+ }
+
+ r = chase_symlinks(image, NULL, CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret);
+ if (r < 0)
+ return log_error_errno(r, "Cannot normalize specified image path '%s': %m", image);
+
+ return 0;
+}
+
+static int extract_prefix(const char *path, char **ret) {
+ _cleanup_free_ char *name = NULL;
+ const char *bn, *underscore;
+ size_t m;
+
+ bn = basename(path);
+
+ underscore = strchr(bn, '_');
+ if (underscore)
+ m = underscore - bn;
+ else {
+ const char *e;
+
+ e = endswith(bn, ".raw");
+ if (!e)
+ e = strchr(bn, 0);
+
+ m = e - bn;
+ }
+
+ name = strndup(bn, m);
+ if (!name)
+ return -ENOMEM;
+
+ /* A slightly reduced version of what's permitted in unit names. With ':' and '\' are removed, as well as '_'
+ * which we use as delimiter for the second part of the image string, which we ignore for now. */
+ if (!in_charset(name, DIGITS LETTERS "-."))
+ return -EINVAL;
+
+ if (!filename_is_valid(name))
+ return -EINVAL;
+
+ *ret = TAKE_PTR(name);
+
+ return 0;
+}
+
+static int determine_matches(const char *image, char **l, bool allow_any, char ***ret) {
+ _cleanup_strv_free_ char **k = NULL;
+ int r;
+
+ /* Determine the matches to apply. If the list is empty we derive the match from the image name. If the list
+ * contains exactly the "-" we return a wildcard list (which is the empty list), but only if this is expressly
+ * permitted. */
+
+ if (strv_isempty(l)) {
+ char *prefix;
+
+ r = extract_prefix(image, &prefix);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract prefix of image name '%s': %m", image);
+
+ if (!arg_quiet)
+ log_info("(Matching unit files with prefix '%s'.)", prefix);
+
+ r = strv_consume(&k, prefix);
+ if (r < 0)
+ return log_oom();
+
+ } else if (strv_equal(l, STRV_MAKE("-"))) {
+
+ if (!allow_any) {
+ log_error("Refusing all unit file match.");
+ return -EINVAL;
+ }
+
+ if (!arg_quiet)
+ log_info("(Matching all unit files.)");
+ } else {
+
+ k = strv_copy(l);
+ if (!k)
+ return log_oom();
+
+ if (!arg_quiet) {
+ _cleanup_free_ char *joined = NULL;
+
+ joined = strv_join(k, "', '");
+ if (!joined)
+ return log_oom();
+
+ log_info("(Matching unit files with prefixes '%s'.)", joined);
+ }
+ }
+
+ *ret = TAKE_PTR(k);
+
+ return 0;
+}
+
+static int acquire_bus(sd_bus **bus) {
+ int r;
+
+ assert(bus);
+
+ if (*bus)
+ return 0;
+
+ r = bus_connect_transport(arg_transport, arg_host, false, bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to bus: %m");
+
+ (void) sd_bus_set_allow_interactive_authorization(*bus, arg_ask_password);
+
+ return 0;
+}
+
+static int maybe_reload(sd_bus **bus) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ int r;
+
+ if (!arg_reload)
+ return 0;
+
+ r = acquire_bus(bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_new_method_call(
+ *bus,
+ &m,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "Reload");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ /* Reloading the daemon may take long, hence set a longer timeout here */
+ r = sd_bus_call(*bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
+static int inspect_image(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_strv_free_ char **matches = NULL;
+ _cleanup_free_ char *image = NULL;
+ bool nl = false, header = false;
+ const void *data;
+ const char *path;
+ size_t sz;
+ int r;
+
+ r = determine_image(argv[1], false, &image);
+ if (r < 0)
+ return r;
+
+ r = determine_matches(argv[1], argv + 2, true, &matches);
+ if (r < 0)
+ return r;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "GetImageMetadata");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "s", image);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, matches);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, 0, &error, &reply);
+ if (r < 0)
+ return log_error_errno(r, "Failed to inspect image metadata: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_read(reply, "s", &path);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_array(reply, 'y', &data, &sz);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ (void) pager_open(arg_no_pager, false);
+
+ if (arg_cat) {
+ printf("%s-- OS Release: --%s\n", ansi_highlight(), ansi_normal());
+ fwrite(data, sz, 1, stdout);
+ fflush(stdout);
+ nl = true;
+ } else {
+ _cleanup_free_ char *pretty_portable = NULL, *pretty_os = NULL;
+
+ _cleanup_fclose_ FILE *f;
+
+ f = fmemopen((void*) data, sz, "re");
+ if (!f)
+ return log_error_errno(errno, "Failed to open /etc/os-release buffer: %m");
+
+ r = parse_env_file(f, "/etc/os-release", NEWLINE,
+ "PORTABLE_PRETTY_NAME", &pretty_portable,
+ "PRETTY_NAME", &pretty_os,
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse /etc/os-release: %m");
+
+ printf("Image:\n\t%s\n"
+ "Portable Service:\n\t%s\n"
+ "Operating System:\n\t%s\n",
+ path,
+ strna(pretty_portable),
+ strna(pretty_os));
+ }
+
+ r = sd_bus_message_enter_container(reply, 'a', "{say}");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ const char *name;
+
+ r = sd_bus_message_enter_container(reply, 'e', "say");
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ r = sd_bus_message_read(reply, "s", &name);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_read_array(reply, 'y', &data, &sz);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (arg_cat) {
+ if (nl)
+ fputc('\n', stdout);
+
+ printf("%s-- Unit file: %s --%s\n", ansi_highlight(), name, ansi_normal());
+ fwrite(data, sz, 1, stdout);
+ fflush(stdout);
+ nl = true;
+ } else {
+ if (!header) {
+ fputs("Unit files:\n", stdout);
+ header = true;
+ }
+
+ fputc('\t', stdout);
+ fputs(name, stdout);
+ fputc('\n', stdout);
+ }
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ }
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 0;
+}
+
+static int print_changes(sd_bus_message *m) {
+ int r;
+
+ if (arg_quiet)
+ return 0;
+
+ r = sd_bus_message_enter_container(m, 'a', "(sss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ const char *type, *path, *source;
+
+ r = sd_bus_message_read(m, "(sss)", &type, &path, &source);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ if (streq(type, "symlink"))
+ log_info("Created symlink %s %s %s.", path, special_glyph(ARROW), source);
+ else if (streq(type, "copy")) {
+ if (isempty(source))
+ log_info("Copied %s.", path);
+ else
+ log_info("Copied %s %s %s.", source, special_glyph(ARROW), path);
+ } else if (streq(type, "unlink"))
+ log_info("Removed %s.", path);
+ else if (streq(type, "write"))
+ log_info("Written %s.", path);
+ else if (streq(type, "mkdir"))
+ log_info("Created directory %s.", path);
+ else
+ log_error("Unexpected change: %s/%s/%s", type, path, source);
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int attach_image(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_strv_free_ char **matches = NULL;
+ _cleanup_free_ char *image = NULL;
+ int r;
+
+ r = determine_image(argv[1], false, &image);
+ if (r < 0)
+ return r;
+
+ r = determine_matches(argv[1], argv + 2, false, &matches);
+ if (r < 0)
+ return r;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "AttachImage");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "s", image);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(m, matches);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "sbs", arg_profile, arg_runtime, arg_copy_mode);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, 0, &error, &reply);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach image: %s", bus_error_message(&error, r));
+
+ (void) maybe_reload(&bus);
+
+ print_changes(reply);
+ return 0;
+}
+
+static int detach_image(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_free_ char *image = NULL;
+ int r;
+
+ r = determine_image(argv[1], true, &image);
+ if (r < 0)
+ return r;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "DetachImage",
+ &error,
+ &reply,
+ "sb", image, arg_runtime);
+ if (r < 0)
+ return log_error_errno(r, "Failed to detach image: %s", bus_error_message(&error, r));
+
+ (void) maybe_reload(&bus);
+
+ print_changes(reply);
+ return 0;
+}
+
+static int list_images(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_(table_unrefp) Table *table = NULL;
+ int r;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "ListImages",
+ &error,
+ &reply,
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list images: %s", bus_error_message(&error, r));
+
+ table = table_new("NAME", "TYPE", "RO", "CRTIME", "MTIME", "USAGE", "STATE");
+ if (!table)
+ return log_oom();
+
+ r = sd_bus_message_enter_container(reply, 'a', "(ssbtttso)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ for (;;) {
+ const char *name, *type, *state;
+ uint64_t crtime, mtime, usage;
+ TableCell *cell;
+ bool ro_bool;
+ int ro_int;
+
+ r = sd_bus_message_read(reply, "(ssbtttso)", &name, &type, &ro_int, &crtime, &mtime, &usage, &state, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ r = table_add_many(table,
+ TABLE_STRING, name,
+ TABLE_STRING, type);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
+
+ ro_bool = ro_int;
+ r = table_add_cell(table, &cell, TABLE_BOOLEAN, &ro_bool);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
+
+ if (ro_bool) {
+ r = table_set_color(table, cell, ansi_highlight_red());
+ if (r < 0)
+ return log_error_errno(r, "Failed to set table cell color: %m");
+ }
+
+ r = table_add_many(table,
+ TABLE_TIMESTAMP, crtime,
+ TABLE_TIMESTAMP, mtime,
+ TABLE_SIZE, usage);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
+
+ r = table_add_cell(table, &cell, TABLE_STRING, state);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
+
+ if (!streq(state, "detached")) {
+ r = table_set_color(table, cell, ansi_highlight_green());
+ if (r < 0)
+ return log_error_errno(r, "Failed to set table cell color: %m");
+ }
+ }
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (table_get_rows(table) > 1) {
+ r = table_set_sort(table, (size_t) 0, (size_t) -1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to sort table: %m");
+
+ table_set_header(table, arg_legend);
+
+ r = table_print(table, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to show table: %m");
+ }
+
+ if (arg_legend) {
+ if (table_get_rows(table) > 1)
+ printf("\n%zu images listed.\n", table_get_rows(table) - 1);
+ else
+ printf("No images.\n");
+ }
+
+ return 0;
+}
+
+static int remove_image(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ int r, i;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
+ for (i = 1; i < argc; i++) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "RemoveImage");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "s", argv[i]);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ /* This is a slow operation, hence turn off any method call timeouts */
+ r = sd_bus_call(bus, m, USEC_INFINITY, &error, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Could not remove image: %s", bus_error_message(&error, r));
+ }
+
+ return 0;
+}
+
+static int read_only_image(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ int b = true, r;
+
+ if (argc > 2) {
+ b = parse_boolean(argv[2]);
+ if (b < 0)
+ return log_error_errno(b, "Failed to parse boolean argument: %s", argv[2]);
+ }
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "MarkImageReadOnly",
+ &error,
+ NULL,
+ "sb", argv[1], b);
+ if (r < 0)
+ return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
+static int set_limit(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ uint64_t limit;
+ int r;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
+
+ if (STR_IN_SET(argv[argc-1], "-", "none", "infinity"))
+ limit = (uint64_t) -1;
+ else {
+ r = parse_size(argv[argc-1], 1024, &limit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse size: %s", argv[argc-1]);
+ }
+
+ if (argc > 2)
+ /* With two arguments changes the quota limit of the specified image */
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "SetImageLimit",
+ &error,
+ NULL,
+ "st", argv[1], limit);
+ else
+ /* With one argument changes the pool quota limit */
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "SetPoolLimit",
+ &error,
+ NULL,
+ "t", limit);
+
+ if (r < 0)
+ return log_error_errno(r, "Could not set limit: %s", bus_error_message(&error, r));
+
+ return 0;
+}
+
+static int is_image_attached(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_free_ char *image = NULL;
+ const char *state;
+ int r;
+
+ r = determine_image(argv[1], true, &image);
+ if (r < 0)
+ return r;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "GetImageState",
+ &error,
+ &reply,
+ "s", image);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get image state: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_read(reply, "s", &state);
+ if (r < 0)
+ return r;
+
+ if (!arg_quiet)
+ puts(state);
+
+ return streq(state, "detached");
+}
+
+static int dump_profiles(void) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_strv_free_ char **l = NULL;
+ char **i;
+ int r;
+
+ r = acquire_bus(&bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_get_property_strv(
+ bus,
+ "org.freedesktop.portable1",
+ "/org/freedesktop/portable1",
+ "org.freedesktop.portable1.Manager",
+ "Profiles",
+ &error,
+ &l);
+ if (r < 0)
+ return log_error_errno(r, "Failed to acquire list of profiles: %s", bus_error_message(&error, r));
+
+ if (arg_legend)
+ log_info("Available unit profiles:");
+
+ STRV_FOREACH(i, l) {
+ fputs(*i, stdout);
+ fputc('\n', stdout);
+ }
+
+ return 0;
+}
+
+static int help(int argc, char *argv[], void *userdata) {
+
+ (void) pager_open(arg_no_pager, false);
+
+ printf("%s [OPTIONS...] {COMMAND} ...\n\n"
+ "Attach or detach portable services from the local system.\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --no-pager Do not pipe output into a pager\n"
+ " --no-legend Do not show the headers and footers\n"
+ " --no-ask-password Do not ask for system passwords\n"
+ " -H --host=[USER@]HOST Operate on remote host\n"
+ " -M --machine=CONTAINER Operate on local container\n"
+ " -q --quiet Suppress informational messages\n"
+ " -p --profile=PROFILE Pick security profile for portable service\n"
+ " --copy=copy|auto|symlink Prefer copying or symlinks if possible\n"
+ " --runtime Attach portable service until next reboot only\n"
+ " --no-reload Don't reload the system and service manager\n"
+ " --cat When inspecting include unit and os-release file\n"
+ " contents\n\n"
+ "Commands:\n"
+ " list List available portable service images\n"
+ " attach NAME|PATH [PREFIX...]\n"
+ " Attach the specified portable service image\n"
+ " detach NAME|PATH Detach the specified portable service image\n"
+ " inspect NAME|PATH [PREFIX...]\n"
+ " Show details of specified portable service image\n"
+ " is-attached NAME|PATH Query if portable service image is attached\n"
+ " read-only NAME|PATH [BOOL] Mark or unmark portable service image read-only\n"
+ " remove NAME|PATH... Remove a portable service image\n"
+ " set-limit [NAME|PATH] Set image or pool size limit (disk quota)\n"
+ , program_invocation_short_name);
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_NO_PAGER,
+ ARG_NO_LEGEND,
+ ARG_NO_ASK_PASSWORD,
+ ARG_COPY,
+ ARG_RUNTIME,
+ ARG_NO_RELOAD,
+ ARG_CAT,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
+ { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
+ { "host", required_argument, NULL, 'H' },
+ { "machine", required_argument, NULL, 'M' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "profile", required_argument, NULL, 'p' },
+ { "copy", required_argument, NULL, ARG_COPY },
+ { "runtime", no_argument, NULL, ARG_RUNTIME },
+ { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
+ { "cat", no_argument, NULL, ARG_CAT },
+ {}
+ };
+
+ assert(argc >= 0);
+ assert(argv);
+
+ for (;;) {
+ int c;
+
+ c = getopt_long(argc, argv, "hH:M:qp:", options, NULL);
+ if (c < 0)
+ break;
+
+ switch (c) {
+
+ case 'h':
+ help(0, NULL, NULL);
+ return 0;
+
+ case ARG_VERSION:
+ return version();
+
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
+ case ARG_NO_LEGEND:
+ arg_legend = false;
+ break;
+
+ case ARG_NO_ASK_PASSWORD:
+ arg_ask_password = false;
+ break;
+
+ case 'H':
+ arg_transport = BUS_TRANSPORT_REMOTE;
+ arg_host = optarg;
+ break;
+
+ case 'M':
+ arg_transport = BUS_TRANSPORT_MACHINE;
+ arg_host = optarg;
+ break;
+
+ case 'q':
+ arg_quiet = true;
+ break;
+
+ case 'p':
+ if (streq(optarg, "help"))
+ return dump_profiles();
+
+ if (!filename_is_valid(optarg)) {
+ log_error("Unit profile name not valid: %s", optarg);
+ return -EINVAL;
+ }
+
+ arg_profile = optarg;
+ break;
+
+ case ARG_COPY:
+ if (streq(optarg, "auto"))
+ arg_copy_mode = NULL;
+ else if (STR_IN_SET(optarg, "copy", "symlink"))
+ arg_copy_mode = optarg;
+ else if (streq(optarg, "help")) {
+ puts("auto\n"
+ "copy\n"
+ "symlink");
+ return 0;
+ } else {
+ log_error("Failed to parse --copy= argument: %s", optarg);
+ return -EINVAL;
+ }
+
+ break;
+
+ case ARG_RUNTIME:
+ arg_runtime = true;
+ break;
+
+ case ARG_NO_RELOAD:
+ arg_reload = false;
+ break;
+
+ case ARG_CAT:
+ arg_cat = true;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
+ }
+ }
+
+ return 1;
+}
+
+int main(int argc, char *argv[]) {
+
+ static const Verb verbs[] = {
+ { "help", VERB_ANY, VERB_ANY, 0, help },
+ { "list", VERB_ANY, 1, VERB_DEFAULT, list_images },
+ { "attach", 2, VERB_ANY, 0, attach_image },
+ { "detach", 2, 2, 0, detach_image },
+ { "inspect", 2, VERB_ANY, 0, inspect_image },
+ { "is-attached", 2, 2, 0, is_image_attached },
+ { "read-only", 2, 3, 0, read_only_image },
+ { "remove", 2, VERB_ANY, 0, remove_image },
+ { "set-limit", 3, 3, 0, set_limit },
+ {}
+ };
+
+ int r;
+
+ log_parse_environment();
+ log_open();
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ goto finish;
+
+ r = dispatch_verb(argc, argv, verbs, NULL);
+
+finish:
+ pager_close();
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/portable/portabled-bus.c b/src/portable/portabled-bus.c
new file mode 100644
index 0000000000..70fc750fe3
--- /dev/null
+++ b/src/portable/portabled-bus.c
@@ -0,0 +1,402 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "btrfs-util.h"
+#include "bus-common-errors.h"
+#include "bus-util.h"
+#include "fd-util.h"
+#include "io-util.h"
+#include "machine-image.h"
+#include "portable.h"
+#include "portabled-bus.h"
+#include "portabled-image-bus.h"
+#include "portabled-image.h"
+#include "portabled.h"
+#include "strv.h"
+#include "user-util.h"
+
+static int property_get_pool_path(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ assert(bus);
+ assert(reply);
+
+ return sd_bus_message_append(reply, "s", "/var/lib/portables");
+}
+
+static int property_get_pool_usage(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ _cleanup_close_ int fd = -1;
+ uint64_t usage = (uint64_t) -1;
+
+ assert(bus);
+ assert(reply);
+
+ fd = open("/var/lib/portables", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
+ if (fd >= 0) {
+ BtrfsQuotaInfo q;
+
+ if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0)
+ usage = q.referenced;
+ }
+
+ return sd_bus_message_append(reply, "t", usage);
+}
+
+static int property_get_pool_limit(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ _cleanup_close_ int fd = -1;
+ uint64_t size = (uint64_t) -1;
+
+ assert(bus);
+ assert(reply);
+
+ fd = open("/var/lib/portables", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
+ if (fd >= 0) {
+ BtrfsQuotaInfo q;
+
+ if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0)
+ size = q.referenced_max;
+ }
+
+ return sd_bus_message_append(reply, "t", size);
+}
+
+static int property_get_profiles(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ _cleanup_strv_free_ char **l = NULL;
+ int r;
+
+ assert(bus);
+ assert(reply);
+
+ r = portable_get_profiles(&l);
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_append_strv(reply, l);
+}
+
+static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_free_ char *p = NULL;
+ Manager *m = userdata;
+ const char *name;
+ Image *image;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ r = sd_bus_message_read(message, "s", &name);
+ if (r < 0)
+ return r;
+
+ r = bus_image_acquire(m, message, name, NULL, BUS_IMAGE_REFUSE_BY_PATH, NULL, &image, error);
+ if (r < 0)
+ return r;
+
+ r = bus_image_path(image, &p);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(message, "o", p);
+}
+
+static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
+ Manager *m = userdata;
+ Image *image;
+ Iterator i;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ images = hashmap_new(&string_hash_ops);
+ if (!images)
+ return -ENOMEM;
+
+ r = manager_image_cache_discover(m, images, error);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_new_method_return(message, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "(ssbtttso)");
+ if (r < 0)
+ return r;
+
+ HASHMAP_FOREACH(image, images, i) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_state = SD_BUS_ERROR_NULL;
+ PortableState state = _PORTABLE_STATE_INVALID;
+ _cleanup_free_ char *p = NULL;
+
+ r = bus_image_path(image, &p);
+ if (r < 0)
+ return r;
+
+ r = portable_get_state(
+ sd_bus_message_get_bus(message),
+ image->path,
+ 0,
+ &state,
+ &error_state);
+ if (r < 0)
+ log_debug_errno(r, "Failed to get state of image '%s', ignoring: %s",
+ image->path, bus_error_message(&error_state, r));
+
+ r = sd_bus_message_append(reply, "(ssbtttso)",
+ image->name,
+ image_type_to_string(image->type),
+ image->read_only,
+ image->crtime,
+ image->mtime,
+ image->usage,
+ portable_state_to_string(state),
+ p);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
+
+static int redirect_method_to_image(
+ Manager *m,
+ sd_bus_message *message,
+ sd_bus_error *error,
+ int (*method)(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error* error)) {
+
+ const char *name_or_path;
+ int r;
+
+ assert(m);
+ assert(message);
+ assert(method);
+
+ r = sd_bus_message_read(message, "s", &name_or_path);
+ if (r < 0)
+ return r;
+
+ return method(m, message, name_or_path, NULL, error);
+}
+
+static int method_get_image_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(userdata, message, error, bus_image_common_get_os_release);
+}
+
+static int method_get_image_metadata(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(userdata, message, error, bus_image_common_get_metadata);
+}
+
+static int method_get_image_state(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ const char *name_or_path;
+ PortableState state;
+ int r;
+
+ assert(message);
+
+ r = sd_bus_message_read(message, "s", &name_or_path);
+ if (r < 0)
+ return r;
+
+ r = portable_get_state(
+ sd_bus_message_get_bus(message),
+ name_or_path,
+ 0,
+ &state,
+ error);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(message, "s", portable_state_to_string(state));
+}
+
+static int method_attach_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(userdata, message, error, bus_image_common_attach);
+}
+
+static int method_detach_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ PortableChange *changes = NULL;
+ Manager *m = userdata;
+ size_t n_changes = 0;
+ const char *name_or_path;
+ int r, runtime;
+
+ assert(message);
+ assert(m);
+
+ /* Note that we do not redirect detaching to the image object here, because we want to allow that users can
+ * detach already deleted images too, in case the user already deleted an image before properly detaching
+ * it. */
+
+ r = sd_bus_message_read(message, "sb", &name_or_path, &runtime);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.portable1.attach-images",
+ NULL,
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ r = portable_detach(
+ sd_bus_message_get_bus(message),
+ name_or_path,
+ runtime ? PORTABLE_RUNTIME : 0,
+ &changes,
+ &n_changes,
+ error);
+ if (r < 0)
+ goto finish;
+
+ r = reply_portable_changes(message, changes, n_changes);
+
+finish:
+ portable_changes_free(changes, n_changes);
+ return r;
+}
+
+static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(userdata, message, error, bus_image_common_remove);
+}
+
+static int method_mark_image_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(userdata, message, error, bus_image_common_mark_read_only);
+}
+
+static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return redirect_method_to_image(userdata, message, error, bus_image_common_set_limit);
+}
+
+static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+ uint64_t limit;
+ int r;
+
+ assert(message);
+
+ r = sd_bus_message_read(message, "t", &limit);
+ if (r < 0)
+ return r;
+ if (!FILE_SIZE_VALID_OR_INFINITY(limit))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
+
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.portable1.manage-images",
+ NULL,
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ (void) btrfs_qgroup_set_limit("/var/lib/portables", 0, limit);
+
+ r = btrfs_subvol_set_subtree_quota_limit("/var/lib/portables", 0, limit);
+ if (r == -ENOTTY)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+const sd_bus_vtable manager_vtable[] = {
+ SD_BUS_VTABLE_START(0),
+ SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
+ SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
+ SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
+ SD_BUS_PROPERTY("Profiles", "as", property_get_profiles, 0, 0),
+ SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("ListImages", NULL, "a(ssbtttso)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("GetImageState", "s", "s", method_get_image_state, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("GetImageMetadata", "sas", "saya{say}", method_get_image_metadata, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("AttachImage", "sassbs", "a(sss)", method_attach_image, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("DetachImage", "sb", "a(sss)", method_detach_image, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_VTABLE_END
+};
+
+int reply_portable_changes(sd_bus_message *m, const PortableChange *changes, size_t n_changes) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ size_t i;
+ int r;
+
+ assert(m);
+ assert(changes || n_changes == 0);
+
+ r = sd_bus_message_new_method_return(m, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "(sss)");
+ if (r < 0)
+ return r;
+
+ for (i = 0; i < n_changes; i++) {
+ r = sd_bus_message_append(reply, "(sss)",
+ portable_change_type_to_string(changes[i].type),
+ changes[i].path,
+ changes[i].source);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
diff --git a/src/portable/portabled-bus.h b/src/portable/portabled-bus.h
new file mode 100644
index 0000000000..5810517ca3
--- /dev/null
+++ b/src/portable/portabled-bus.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-bus.h"
+
+#include "portable.h"
+
+extern const sd_bus_vtable manager_vtable[];
+
+int reply_portable_changes(sd_bus_message *m, const PortableChange *changes, size_t n_changes);
diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c
new file mode 100644
index 0000000000..02a2db2352
--- /dev/null
+++ b/src/portable/portabled-image-bus.c
@@ -0,0 +1,731 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "bus-common-errors.h"
+#include "bus-label.h"
+#include "bus-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "io-util.h"
+#include "machine-image.h"
+#include "portable.h"
+#include "portabled-bus.h"
+#include "portabled-image-bus.h"
+#include "portabled-image.h"
+#include "portabled.h"
+#include "process-util.h"
+#include "strv.h"
+#include "user-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType);
+
+int bus_image_common_get_os_release(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name_or_path,
+ Image *image,
+ sd_bus_error *error) {
+
+ int r;
+
+ assert(name_or_path || image);
+ assert(message);
+
+ if (!m) {
+ assert(image);
+ m = image->userdata;
+ }
+
+ r = bus_image_acquire(m,
+ message,
+ name_or_path,
+ image,
+ BUS_IMAGE_AUTHENTICATE_BY_PATH,
+ "org.freedesktop.portable1.inspect-images",
+ &image,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0) /* Will call us back */
+ return 1;
+
+ if (!image->metadata_valid) {
+ r = image_read_metadata(image);
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
+ }
+
+ return bus_reply_pair_array(message, image->os_release);
+}
+
+static int bus_image_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_image_common_get_os_release(NULL, message, NULL, userdata, error);
+}
+
+static int append_fd(sd_bus_message *m, PortableMetadata *d) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *buf = NULL;
+ size_t n;
+ int r;
+
+ assert(m);
+ assert(d);
+ assert(d->fd >= 0);
+
+ f = fdopen(d->fd, "re");
+ if (!f)
+ return -errno;
+
+ d->fd = -1;
+
+ r = read_full_stream(f, &buf, &n);
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_append_array(m, 'y', buf, n);
+}
+
+int bus_image_common_get_metadata(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name_or_path,
+ Image *image,
+ sd_bus_error *error) {
+
+ _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
+ _cleanup_(portable_metadata_hashmap_unrefp) Hashmap *unit_files = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_free_ PortableMetadata **sorted = NULL;
+ _cleanup_strv_free_ char **matches = NULL;
+ size_t i;
+ int r;
+
+ assert(name_or_path || image);
+ assert(message);
+
+ if (!m) {
+ assert(image);
+ m = image->userdata;
+ }
+
+ r = sd_bus_message_read_strv(message, &matches);
+ if (r < 0)
+ return r;
+
+ r = bus_image_acquire(m,
+ message,
+ name_or_path,
+ image,
+ BUS_IMAGE_AUTHENTICATE_BY_PATH,
+ "org.freedesktop.portable1.inspect-images",
+ &image,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0) /* Will call us back */
+ return 1;
+
+ r = portable_extract(
+ image->path,
+ matches,
+ &os_release,
+ &unit_files,
+ error);
+ if (r < 0)
+ return r;
+
+ r = portable_metadata_hashmap_to_sorted_array(unit_files, &sorted);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_new_method_return(message, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "s", image->path);
+ if (r < 0)
+ return r;
+
+ r = append_fd(reply, os_release);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "{say}");
+ if (r < 0)
+ return r;
+
+ for (i = 0; i < hashmap_size(unit_files); i++) {
+
+ r = sd_bus_message_open_container(reply, 'e', "say");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "s", sorted[i]->name);
+ if (r < 0)
+ return r;
+
+ r = append_fd(reply, sorted[i]);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
+
+static int bus_image_method_get_metadata(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_image_common_get_metadata(NULL, message, NULL, userdata, error);
+}
+
+static int bus_image_method_get_state(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Image *image = userdata;
+ PortableState state;
+ int r;
+
+ assert(message);
+ assert(image);
+
+ r = portable_get_state(
+ sd_bus_message_get_bus(message),
+ image->path,
+ 0,
+ &state,
+ error);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(message, "s", portable_state_to_string(state));
+}
+
+int bus_image_common_attach(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name_or_path,
+ Image *image,
+ sd_bus_error *error) {
+
+ _cleanup_strv_free_ char **matches = NULL;
+ PortableChange *changes = NULL;
+ PortableFlags flags = 0;
+ const char *profile, *copy_mode;
+ size_t n_changes = 0;
+ int runtime, r;
+
+ assert(message);
+ assert(name_or_path || image);
+
+ if (!m) {
+ assert(image);
+ m = image->userdata;
+ }
+
+ r = sd_bus_message_read_strv(message, &matches);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(message, "sbs", &profile, &runtime, &copy_mode);
+ if (r < 0)
+ return r;
+
+ if (streq(copy_mode, "symlink"))
+ flags |= PORTABLE_PREFER_SYMLINK;
+ else if (streq(copy_mode, "copy"))
+ flags |= PORTABLE_PREFER_COPY;
+ else if (!isempty(copy_mode))
+ return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Unknown copy mode '%s'", copy_mode);
+
+ if (runtime)
+ flags |= PORTABLE_RUNTIME;
+
+ r = bus_image_acquire(m,
+ message,
+ name_or_path,
+ image,
+ BUS_IMAGE_AUTHENTICATE_ALL,
+ "org.freedesktop.portable1.attach-images",
+ &image,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0) /* Will call us back */
+ return 1;
+
+ r = portable_attach(
+ sd_bus_message_get_bus(message),
+ image->path,
+ matches,
+ profile,
+ flags,
+ &changes,
+ &n_changes,
+ error);
+ if (r < 0)
+ goto finish;
+
+ r = reply_portable_changes(message, changes, n_changes);
+
+finish:
+ portable_changes_free(changes, n_changes);
+ return r;
+}
+
+static int bus_image_method_attach(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_image_common_attach(NULL, message, NULL, userdata, error);
+}
+
+static int bus_image_method_detach(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ PortableChange *changes = NULL;
+ Image *image = userdata;
+ Manager *m = image->userdata;
+ size_t n_changes = 0;
+ int r, runtime;
+
+ assert(message);
+ assert(image);
+ assert(m);
+
+ r = sd_bus_message_read(message, "b", &runtime);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.portable1.attach-images",
+ NULL,
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ r = portable_detach(
+ sd_bus_message_get_bus(message),
+ image->path,
+ runtime ? PORTABLE_RUNTIME : 0,
+ &changes,
+ &n_changes,
+ error);
+ if (r < 0)
+ goto finish;
+
+ r = reply_portable_changes(message, changes, n_changes);
+
+finish:
+ portable_changes_free(changes, n_changes);
+ return r;
+}
+
+int bus_image_common_remove(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name_or_path,
+ Image *image,
+ sd_bus_error *error) {
+
+ _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
+ _cleanup_(sigkill_waitp) pid_t child = 0;
+ PortableState state;
+ int r;
+
+ assert(message);
+ assert(name_or_path || image);
+
+ if (!m) {
+ assert(image);
+ m = image->userdata;
+ }
+
+ if (m->n_operations >= OPERATIONS_MAX)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
+
+ r = bus_image_acquire(m,
+ message,
+ name_or_path,
+ image,
+ BUS_IMAGE_AUTHENTICATE_ALL,
+ "org.freedesktop.portable1.manage-images",
+ &image,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ r = portable_get_state(
+ sd_bus_message_get_bus(message),
+ image->path,
+ 0,
+ &state,
+ error);
+ if (r < 0)
+ return r;
+
+ if (state != PORTABLE_DETACHED)
+ return sd_bus_error_set_errnof(error, EBUSY, "Image '%s' is not detached, refusing.", image->path);
+
+ if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
+ return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
+
+ r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
+ if (r == 0) {
+ errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
+
+ r = image_remove(image);
+ if (r < 0) {
+ (void) write(errno_pipe_fd[1], &r, sizeof(r));
+ _exit(EXIT_FAILURE);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
+
+ r = operation_new(m, child, message, errno_pipe_fd[0], NULL);
+ if (r < 0)
+ return r;
+
+ child = 0;
+ errno_pipe_fd[0] = -1;
+
+ return 1;
+}
+
+static int bus_image_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_image_common_remove(NULL, message, NULL, userdata, error);
+}
+
+int bus_image_common_mark_read_only(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name_or_path,
+ Image *image,
+ sd_bus_error *error) {
+
+ int r, read_only;
+
+ assert(message);
+ assert(name_or_path || image);
+
+ if (!m) {
+ assert(image);
+ m = image->userdata;
+ }
+
+ r = sd_bus_message_read(message, "b", &read_only);
+ if (r < 0)
+ return r;
+
+ r = bus_image_acquire(m,
+ message,
+ name_or_path,
+ image,
+ BUS_IMAGE_AUTHENTICATE_ALL,
+ "org.freedesktop.portable1.manage-images",
+ &image,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ r = image_read_only(image, read_only);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int bus_image_method_mark_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_image_common_mark_read_only(NULL, message, NULL, userdata, error);
+}
+
+int bus_image_common_set_limit(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name_or_path,
+ Image *image,
+ sd_bus_error *error) {
+
+ uint64_t limit;
+ int r;
+
+ assert(message);
+ assert(name_or_path || image);
+
+ if (!m) {
+ assert(image);
+ m = image->userdata;
+ }
+
+ r = sd_bus_message_read(message, "t", &limit);
+ if (r < 0)
+ return r;
+ if (!FILE_SIZE_VALID_OR_INFINITY(limit))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
+
+ r = bus_image_acquire(m,
+ message,
+ name_or_path,
+ image,
+ BUS_IMAGE_AUTHENTICATE_ALL,
+ "org.freedesktop.portable1.manage-images",
+ &image,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ r = image_set_limit(image, limit);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int bus_image_method_set_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return bus_image_common_set_limit(NULL, message, NULL, userdata, error);
+}
+
+const sd_bus_vtable image_vtable[] = {
+ SD_BUS_VTABLE_START(0),
+ SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0),
+ SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0),
+ SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0),
+ SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0),
+ SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0),
+ SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0),
+ SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0),
+ SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0),
+ SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0),
+ SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0),
+ SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_image_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("GetMedatadata", "as", "saya{say}", bus_image_method_get_metadata, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("GetState", NULL, "s", bus_image_method_get_state, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Attach", "assbs", "a(sss)", bus_image_method_attach, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Detach", "b", "a(sss)", bus_image_method_detach, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_VTABLE_END
+};
+
+int bus_image_path(Image *image, char **ret) {
+ assert(image);
+ assert(ret);
+
+ if (!image->discoverable)
+ return -EINVAL;
+
+ return sd_bus_path_encode("/org/freedesktop/portable1/image", image->name, ret);
+}
+
+int bus_image_acquire(
+ Manager *m,
+ sd_bus_message *message,
+ const char *name_or_path,
+ Image *image,
+ ImageAcquireMode mode,
+ const char *polkit_action,
+ Image **ret,
+ sd_bus_error *error) {
+
+ _cleanup_(image_unrefp) Image *loaded = NULL;
+ Image *cached;
+ int r;
+
+ assert(m);
+ assert(message);
+ assert(name_or_path || image);
+ assert(mode >= 0);
+ assert(mode < _BUS_IMAGE_ACQUIRE_MODE_MAX);
+ assert(polkit_action || mode == BUS_IMAGE_REFUSE_BY_PATH);
+ assert(ret);
+
+ /* Acquires an 'Image' object if not acquired yet, and enforces necessary authentication while doing so. */
+
+ if (mode == BUS_IMAGE_AUTHENTICATE_ALL) {
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ polkit_action,
+ NULL,
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0) { /* Will call us back */
+ *ret = NULL;
+ return 0;
+ }
+ }
+
+ /* Already passed in? */
+ if (image) {
+ *ret = image;
+ return 1;
+ }
+
+ /* Let's see if this image is already cached? */
+ cached = manager_image_cache_get(m, name_or_path);
+ if (cached) {
+ *ret = cached;
+ return 1;
+ }
+
+ if (image_name_is_valid(name_or_path)) {
+
+ /* If it's a short name, let's search for it */
+ r = image_find(IMAGE_PORTABLE, name_or_path, &loaded);
+ if (r == -ENOENT)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PORTABLE_IMAGE, "No image '%s' found.", name_or_path);
+
+ /* other errors are handled below… */
+ } else {
+ /* Don't accept path if this is always forbidden */
+ if (mode == BUS_IMAGE_REFUSE_BY_PATH)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Expected image name, not path in place of '%s'.", name_or_path);
+
+ if (!path_is_absolute(name_or_path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is not valid or not a valid path.", name_or_path);
+
+ if (!path_is_normalized(name_or_path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image path '%s' is not normalized.", name_or_path);
+
+ if (mode == BUS_IMAGE_AUTHENTICATE_BY_PATH) {
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ polkit_action,
+ NULL,
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0) { /* Will call us back */
+ *ret = NULL;
+ return 0;
+ }
+ }
+
+ r = image_from_path(name_or_path, &loaded);
+ }
+ if (r < 0)
+ return r;
+
+ /* Add what we just loaded to the cache. This has as side-effect that the object stays in memory until the
+ * cache is purged again, i.e. at least for the current event loop iteration, which is all we need, and which
+ * means we don't actually need to ref the return object. */
+ r = manager_image_cache_add(m, loaded);
+ if (r < 0)
+ return r;
+
+ *ret = loaded;
+ return 1;
+}
+
+int bus_image_object_find(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ void *userdata,
+ void **found,
+ sd_bus_error *error) {
+
+ _cleanup_free_ char *e = NULL;
+ Manager *m = userdata;
+ Image *image = NULL;
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(interface);
+ assert(found);
+
+ r = sd_bus_path_decode(path, "/org/freedesktop/portable1/image", &e);
+ if (r < 0)
+ return 0;
+ if (r == 0)
+ goto not_found;
+
+ r = bus_image_acquire(m, sd_bus_get_current_message(bus), e, NULL, BUS_IMAGE_REFUSE_BY_PATH, NULL, &image, error);
+ if (r == -ENOENT)
+ goto not_found;
+ if (r < 0)
+ return r;
+
+ *found = image;
+ return 1;
+
+not_found:
+ *found = NULL;
+ return 0;
+}
+
+int bus_image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+ _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
+ _cleanup_strv_free_ char **l = NULL;
+ size_t n_allocated = 0, n = 0;
+ Manager *m = userdata;
+ Image *image;
+ Iterator i;
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(nodes);
+
+ images = hashmap_new(&string_hash_ops);
+ if (!images)
+ return -ENOMEM;
+
+ r = manager_image_cache_discover(m, images, error);
+ if (r < 0)
+ return r;
+
+ HASHMAP_FOREACH(image, images, i) {
+ char *p;
+
+ r = bus_image_path(image, &p);
+ if (r < 0)
+ return r;
+
+ if (!GREEDY_REALLOC(l, n_allocated, n+2)) {
+ free(p);
+ return -ENOMEM;
+ }
+
+ l[n++] = p;
+ l[n] = NULL;
+ }
+
+ *nodes = TAKE_PTR(l);
+
+ return 1;
+}
diff --git a/src/portable/portabled-image-bus.h b/src/portable/portabled-image-bus.h
new file mode 100644
index 0000000000..81c17f68af
--- /dev/null
+++ b/src/portable/portabled-image-bus.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-bus.h"
+
+#include "machine-image.h"
+#include "portabled.h"
+
+int bus_image_common_get_os_release(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
+int bus_image_common_get_metadata(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
+int bus_image_common_attach(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
+int bus_image_common_remove(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
+int bus_image_common_mark_read_only(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
+int bus_image_common_set_limit(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error);
+
+extern const sd_bus_vtable image_vtable[];
+
+int bus_image_path(Image *image, char **ret);
+
+/* So here's some complexity: some of operations can either take an image name, or a fully qualified file system path
+ * to an image. We need to authenticate differently when processing these two: images referenced via simple image names
+ * mean the images are located in the image search path and thus safe for limited read access for unprivileged
+ * clients. For operations on images located anywhere else we need explicit authentication however, so that
+ * unprivileged clients can't make us open arbitrary files in the file system.
+ *
+ * The "Image" bus objects directly represent images in the image search path, but do not exist for path-referenced
+ * images. Hence, when requesting a bus object we need to refuse references by file system path, but still allow
+ * references by image name. Depending on the operation to execute potentially we need to authenticate in all cases. */
+
+typedef enum ImageAcquireMode {
+ BUS_IMAGE_REFUSE_BY_PATH, /* allow by name + prohibit by path */
+ BUS_IMAGE_AUTHENTICATE_BY_PATH, /* allow by name + polkit by path */
+ BUS_IMAGE_AUTHENTICATE_ALL, /* polkit by name + polkit by path */
+ _BUS_IMAGE_ACQUIRE_MODE_MAX,
+ _BUS_IMAGE_ACQUIRE_MODE_INVALID = -1
+} ImageAcquireMode;
+
+int bus_image_acquire(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, ImageAcquireMode mode, const char *polkit_action, Image **ret, sd_bus_error *error);
+
+int bus_image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
+int bus_image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
diff --git a/src/portable/portabled-image.c b/src/portable/portabled-image.c
new file mode 100644
index 0000000000..c58197c9a6
--- /dev/null
+++ b/src/portable/portabled-image.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "portable.h"
+#include "portabled-image.h"
+#include "portabled.h"
+
+Image *manager_image_cache_get(Manager *m, const char *name_or_path) {
+ assert(m);
+
+ return hashmap_get(m->image_cache, name_or_path);
+}
+
+static int image_cache_flush(sd_event_source *s, void *userdata) {
+ Manager *m = userdata;
+
+ assert(s);
+ assert(m);
+
+ hashmap_clear_with_destructor(m->image_cache, image_unref);
+ return 0;
+}
+
+static int manager_image_cache_initialize(Manager *m) {
+ int r;
+
+ assert(m);
+
+ r = hashmap_ensure_allocated(&m->image_cache, &string_hash_ops);
+ if (r < 0)
+ return r;
+
+ /* We flush the cache as soon as we are idle again */
+ if (!m->image_cache_defer_event) {
+ r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_cache_flush, m);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int manager_image_cache_add(Manager *m, Image *image) {
+ int r;
+
+ assert(m);
+
+ /* We add the specified image to the cache under two keys.
+ *
+ * 1. Always under its path
+ *
+ * 2. If the image was discovered in the search path (i.e. its discoverable boolean set) we'll also add it
+ * under its short name.
+ *
+ */
+
+ r = manager_image_cache_initialize(m);
+ if (r < 0)
+ return r;
+
+ image->userdata = m;
+
+ r = hashmap_put(m->image_cache, image->path, image);
+ if (r < 0)
+ return r;
+
+ image_ref(image);
+
+ if (image->discoverable) {
+ r = hashmap_put(m->image_cache, image->name, image);
+ if (r < 0)
+ return r;
+
+ image_ref(image);
+ }
+
+ return 0;
+}
+
+int manager_image_cache_discover(Manager *m, Hashmap *images, sd_bus_error *error) {
+ Image *image;
+ Iterator i;
+ int r;
+
+ assert(m);
+
+ /* A wrapper around image_discover() (for finding images in search path) and portable_discover_attached() (for
+ * finding attached images). */
+
+ r = image_discover(IMAGE_PORTABLE, images);
+ if (r < 0)
+ return r;
+
+ HASHMAP_FOREACH(image, images, i)
+ (void) manager_image_cache_add(m, image);
+
+ return 0;
+}
diff --git a/src/portable/portabled-image.h b/src/portable/portabled-image.h
new file mode 100644
index 0000000000..f29bd89e83
--- /dev/null
+++ b/src/portable/portabled-image.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "hashmap.h"
+#include "machine-image.h"
+#include "portabled.h"
+
+Image *manager_image_cache_get(Manager *m, const char *name_or_path);
+
+int manager_image_cache_add(Manager *m, Image *image);
+
+int manager_image_cache_discover(Manager *m, Hashmap *images, sd_bus_error *error);
diff --git a/src/portable/portabled-operation.c b/src/portable/portabled-operation.c
new file mode 100644
index 0000000000..305c96ca6f
--- /dev/null
+++ b/src/portable/portabled-operation.c
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "portabled-operation.h"
+#include "process-util.h"
+
+static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ Operation *o = userdata;
+ int r;
+
+ assert(o);
+ assert(si);
+
+ log_debug("Operating " PID_FMT " is now complete with code=%s status=%i",
+ o->pid,
+ sigchld_code_to_string(si->si_code), si->si_status);
+
+ o->pid = 0;
+
+ if (si->si_code != CLD_EXITED) {
+ r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
+ goto fail;
+ }
+
+ if (si->si_status == EXIT_SUCCESS)
+ r = 0;
+ else if (read(o->errno_fd, &r, sizeof(r)) != sizeof(r)) { /* Try to acquire error code for failed operation */
+ r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed.");
+ goto fail;
+ }
+
+ if (o->done) {
+ /* A completion routine is set for this operation, call it. */
+ r = o->done(o, r, &error);
+ if (r < 0) {
+ if (!sd_bus_error_is_set(&error))
+ sd_bus_error_set_errno(&error, r);
+
+ goto fail;
+ }
+
+ } else {
+ /* The default operation when done is to simply return an error on failure or an empty success
+ * message on success. */
+ if (r < 0) {
+ sd_bus_error_set_errno(&error, r);
+ goto fail;
+ }
+
+ r = sd_bus_reply_method_return(o->message, NULL);
+ if (r < 0)
+ log_error_errno(r, "Failed to reply to message: %m");
+ }
+
+ operation_free(o);
+ return 0;
+
+fail:
+ r = sd_bus_reply_method_error(o->message, &error);
+ if (r < 0)
+ log_error_errno(r, "Failed to reply to message: %m");
+
+ operation_free(o);
+ return 0;
+}
+
+int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret) {
+ Operation *o;
+ int r;
+
+ assert(manager);
+ assert(child > 1);
+ assert(message);
+ assert(errno_fd >= 0);
+
+ o = new0(Operation, 1);
+ if (!o)
+ return -ENOMEM;
+
+ o->extra_fd = -1;
+
+ r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o);
+ if (r < 0) {
+ free(o);
+ return r;
+ }
+
+ o->pid = child;
+ o->message = sd_bus_message_ref(message);
+ o->errno_fd = errno_fd;
+
+ LIST_PREPEND(operations, manager->operations, o);
+ manager->n_operations++;
+ o->manager = manager;
+
+ log_debug("Started new operation " PID_FMT ".", child);
+
+ /* At this point we took ownership of both the child and the errno file descriptor! */
+
+ if (ret)
+ *ret = o;
+
+ return 0;
+}
+
+Operation *operation_free(Operation *o) {
+ if (!o)
+ return NULL;
+
+ sd_event_source_unref(o->event_source);
+
+ safe_close(o->errno_fd);
+ safe_close(o->extra_fd);
+
+ if (o->pid > 1)
+ (void) sigkill_wait(o->pid);
+
+ sd_bus_message_unref(o->message);
+
+ if (o->manager) {
+ LIST_REMOVE(operations, o->manager->operations, o);
+ o->manager->n_operations--;
+ }
+
+ return mfree(o);
+}
diff --git a/src/portable/portabled-operation.h b/src/portable/portabled-operation.h
new file mode 100644
index 0000000000..701f399bbb
--- /dev/null
+++ b/src/portable/portabled-operation.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/types.h>
+
+#include "sd-bus.h"
+#include "sd-event.h"
+
+#include "list.h"
+
+typedef struct Operation Operation;
+
+#include "portabled.h"
+
+#define OPERATIONS_MAX 64
+
+struct Operation {
+ Manager *manager;
+ pid_t pid;
+ sd_bus_message *message;
+ int errno_fd;
+ int extra_fd;
+ sd_event_source *event_source;
+ int (*done)(Operation *o, int ret, sd_bus_error *error);
+ LIST_FIELDS(Operation, operations);
+};
+
+int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret);
+Operation *operation_free(Operation *o);
diff --git a/src/portable/portabled.c b/src/portable/portabled.c
new file mode 100644
index 0000000000..53faa09bac
--- /dev/null
+++ b/src/portable/portabled.c
@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-bus.h"
+#include "sd-daemon.h"
+
+#include "alloc-util.h"
+#include "bus-util.h"
+#include "def.h"
+#include "portabled-bus.h"
+#include "portabled-image-bus.h"
+#include "portabled.h"
+#include "process-util.h"
+#include "signal-util.h"
+
+static Manager* manager_unref(Manager *m);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
+
+static int manager_new(Manager **ret) {
+ _cleanup_(manager_unrefp) Manager *m = NULL;
+ int r;
+
+ assert(ret);
+
+ m = new0(Manager, 1);
+ if (!m)
+ return -ENOMEM;
+
+ r = sd_event_default(&m->event);
+ if (r < 0)
+ return r;
+
+ r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ (void) sd_event_set_watchdog(m->event, true);
+
+ *ret = TAKE_PTR(m);
+ return 0;
+}
+
+static Manager* manager_unref(Manager *m) {
+ assert(m);
+
+ hashmap_free_with_destructor(m->image_cache, image_unref);
+
+ sd_event_source_unref(m->image_cache_defer_event);
+
+ bus_verify_polkit_async_registry_free(m->polkit_registry);
+
+ sd_bus_unref(m->bus);
+ sd_event_unref(m->event);
+
+ return mfree(m);
+}
+
+static int manager_connect_bus(Manager *m) {
+ int r;
+
+ assert(m);
+ assert(!m->bus);
+
+ r = sd_bus_default_system(&m->bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to system bus: %m");
+
+ r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/portable1", "org.freedesktop.portable1.Manager", manager_vtable, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add manager object vtable: %m");
+
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/portable1/image", "org.freedesktop.portable1.Image", image_vtable, bus_image_object_find, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add image object vtable: %m");
+
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/portable1/image", bus_image_node_enumerator, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add image enumerator: %m");
+
+ r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.portable1", 0, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to request name: %m");
+
+ r = sd_bus_attach_event(m->bus, m->event, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach bus to event loop: %m");
+
+ (void) sd_bus_set_exit_on_disconnect(m->bus, true);
+
+ return 0;
+}
+
+static int manager_startup(Manager *m) {
+ int r;
+
+ assert(m);
+
+ r = manager_connect_bus(m);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static bool check_idle(void *userdata) {
+ Manager *m = userdata;
+
+ return !m->operations;
+}
+
+static int manager_run(Manager *m) {
+ assert(m);
+
+ return bus_event_loop_with_idle(
+ m->event,
+ m->bus,
+ "org.freedesktop.portable1",
+ DEFAULT_EXIT_USEC,
+ check_idle, m);
+}
+
+int main(int argc, char *argv[]) {
+ _cleanup_(manager_unrefp) Manager *m = NULL;
+ int r;
+
+ log_set_target(LOG_TARGET_AUTO);
+ log_parse_environment();
+ log_open();
+
+ umask(0022);
+
+ if (argc != 1) {
+ log_error("This program takes no arguments.");
+ r = -EINVAL;
+ goto finish;
+ }
+
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, -1) >= 0);
+
+ r = manager_new(&m);
+ if (r < 0) {
+ log_error_errno(r, "Failed to allocate manager object: %m");
+ goto finish;
+ }
+
+ r = manager_startup(m);
+ if (r < 0) {
+ log_error_errno(r, "Failed to fully start up daemon: %m");
+ goto finish;
+ }
+
+ log_debug("systemd-portabled running as pid " PID_FMT, getpid_cached());
+
+ sd_notify(false,
+ "READY=1\n"
+ "STATUS=Processing requests...");
+
+ r = manager_run(m);
+
+ log_debug("systemd-portabled stopped as pid " PID_FMT, getpid_cached());
+
+finish:
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
+}
diff --git a/src/portable/portabled.h b/src/portable/portabled.h
new file mode 100644
index 0000000000..00461edfca
--- /dev/null
+++ b/src/portable/portabled.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-bus.h"
+#include "sd-event.h"
+
+#include "hashmap.h"
+#include "list.h"
+
+typedef struct Manager Manager;
+
+#include "portabled-operation.h"
+
+struct Manager {
+ sd_event *event;
+ sd_bus *bus;
+
+ Hashmap *polkit_registry;
+
+ Hashmap *image_cache;
+ sd_event_source *image_cache_defer_event;
+
+ LIST_HEAD(Operation, operations);
+ unsigned n_operations;
+};
diff --git a/src/portable/profile/default/service.conf b/src/portable/profile/default/service.conf
new file mode 100644
index 0000000000..792be50229
--- /dev/null
+++ b/src/portable/profile/default/service.conf
@@ -0,0 +1,32 @@
+# The "default" security profile for services, i.e. a number of useful restrictions
+
+[Service]
+MountAPIVFS=yes
+TemporaryFileSystem=/run
+BindReadOnlyPaths=/run/systemd/notify
+BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout
+BindReadOnlyPaths=/etc/machine-id
+BindReadOnlyPaths=/etc/resolv.conf
+BindReadOnlyPaths=/run/dbus/system_bus_socket
+DynamicUser=yes
+RemoveIPC=yes
+CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER \
+ CAP_FSETID CAP_IPC_LOCK CAP_IPC_OWNER CAP_KILL CAP_MKNOD CAP_NET_ADMIN \
+ CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_SETGID CAP_SETPCAP \
+ CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_RESOURCE
+PrivateTmp=yes
+PrivateDevices=yes
+PrivateUsers=yes
+ProtectSystem=strict
+ProtectHome=yes
+ProtectKernelTunables=yes
+ProtectKernelModules=yes
+ProtectControlGroups=yes
+RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
+LockPersonality=yes
+MemoryDenyWriteExecute=yes
+RestrictRealtime=yes
+RestrictNamespaces=yes
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
+SystemCallArchitectures=native
diff --git a/src/portable/profile/nonetwork/service.conf b/src/portable/profile/nonetwork/service.conf
new file mode 100644
index 0000000000..c81cebe03f
--- /dev/null
+++ b/src/portable/profile/nonetwork/service.conf
@@ -0,0 +1,32 @@
+# The "nonetwork" security profile for services, i.e. like "default" but without networking
+
+[Service]
+MountAPIVFS=yes
+TemporaryFileSystem=/run
+BindReadOnlyPaths=/run/systemd/notify
+BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout
+BindReadOnlyPaths=/etc/machine-id
+BindReadOnlyPaths=/run/dbus/system_bus_socket
+DynamicUser=yes
+RemoveIPC=yes
+CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER \
+ CAP_FSETID CAP_IPC_LOCK CAP_IPC_OWNER CAP_KILL CAP_MKNOD CAP_SETGID CAP_SETPCAP \
+ CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_RESOURCE
+PrivateTmp=yes
+PrivateDevices=yes
+PrivateUsers=yes
+ProtectSystem=strict
+ProtectHome=yes
+ProtectKernelTunables=yes
+ProtectKernelModules=yes
+ProtectControlGroups=yes
+RestrictAddressFamilies=AF_UNIX AF_NETLINK
+LockPersonality=yes
+MemoryDenyWriteExecute=yes
+RestrictRealtime=yes
+RestrictNamespaces=yes
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
+SystemCallArchitectures=native
+PrivateNetwork=yes
+IPAddressDeny=any
diff --git a/src/portable/profile/strict/service.conf b/src/portable/profile/strict/service.conf
new file mode 100644
index 0000000000..d10fb5a1e8
--- /dev/null
+++ b/src/portable/profile/strict/service.conf
@@ -0,0 +1,31 @@
+# The "strict" security profile for services, all options turned on
+
+[Service]
+MountAPIVFS=yes
+TemporaryFileSystem=/run
+BindReadOnlyPaths=/run/systemd/notify
+BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout
+BindReadOnlyPaths=/etc/machine-id
+DynamicUser=yes
+RemoveIPC=yes
+CapabilityBoundingSet=
+PrivateTmp=yes
+PrivateDevices=yes
+PrivateUsers=yes
+ProtectSystem=strict
+ProtectHome=yes
+ProtectKernelTunables=yes
+ProtectKernelModules=yes
+ProtectControlGroups=yes
+RestrictAddressFamilies=AF_UNIX
+LockPersonality=yes
+NoNewPrivileges=yes
+MemoryDenyWriteExecute=yes
+RestrictRealtime=yes
+RestrictNamespaces=yes
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
+SystemCallArchitectures=native
+PrivateNetwork=yes
+IPAddressDeny=any
+TasksMax=4
diff --git a/src/portable/profile/trusted/service.conf b/src/portable/profile/trusted/service.conf
new file mode 100644
index 0000000000..9a6af70b93
--- /dev/null
+++ b/src/portable/profile/trusted/service.conf
@@ -0,0 +1,7 @@
+# The "trusted" profile for services, i.e. no restrictions are applied
+
+[Service]
+MountAPIVFS=yes
+BindPaths=/run
+BindReadOnlyPaths=/etc/machine-id
+BindReadOnlyPaths=/etc/resolv.conf
diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c
index 1bf718e4f6..d891f18b65 100644
--- a/src/quotacheck/quotacheck.c
+++ b/src/quotacheck/quotacheck.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdbool.h>
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
index 23a6fda08c..223b56306c 100644
--- a/src/random-seed/random-seed.c
+++ b/src/random-seed/random-seed.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c
index 2762fa7e89..44b2edec05 100644
--- a/src/rc-local-generator/rc-local-generator.c
+++ b/src/rc-local-generator/rc-local-generator.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2011 Michal Schmidt
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c
index c61777c3fe..9220a00215 100644
--- a/src/remount-fs/remount-fs.c
+++ b/src/remount-fs/remount-fs.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <mntent.h>
diff --git a/src/reply-password/reply-password.c b/src/reply-password/reply-password.c
index 6f82bf73f0..efb68a354f 100644
--- a/src/reply-password/reply-password.c
+++ b/src/reply-password/reply-password.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stddef.h>
diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c
index 0c366b5e8e..c96f60a064 100644
--- a/src/resolve/dns-type.c
+++ b/src/resolve/dns-type.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/socket.h>
#include <errno.h>
diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h
index 583ceee191..8721536b5d 100644
--- a/src/resolve/dns-type.h
+++ b/src/resolve/dns-type.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "macro.h"
/* DNS record types, taken from
diff --git a/src/resolve/meson.build b/src/resolve/meson.build
index 16ba83ef88..15f3835d55 100644
--- a/src/resolve/meson.build
+++ b/src/resolve/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
basic_dns_sources = files('''
resolved-dns-dnssec.c
@@ -80,7 +65,12 @@ systemd_resolved_sources = files('''
resolved-etc-hosts.c
'''.split())
-systemd_resolve_sources = files('resolve-tool.c')
+resolvectl_sources = files('''
+ resolvconf-compat.c
+ resolvconf-compat.h
+ resolvectl.c
+ resolvectl.h
+'''.split())
############################################################
@@ -149,6 +139,11 @@ libsystemd_resolve_core = static_library(
systemd_resolved_sources += [resolved_gperf_c, resolved_dnssd_gperf_c]
+systemd_resolved_dependencies = [threads, libgpg_error, libm, libidn]
+if conf.get('ENABLE_DNS_OVER_TLS') == 1
+ systemd_resolved_dependencies += [libgnutls]
+endif
+
if conf.get('ENABLE_RESOLVE') == 1
install_data('org.freedesktop.resolve1.conf',
install_dir : dbuspolicydir)
diff --git a/src/resolve/resolv.conf b/src/resolve/resolv.conf
index 34a6b9257f..ffc460dbf2 100644
--- a/src/resolve/resolv.conf
+++ b/src/resolve/resolv.conf
@@ -4,7 +4,7 @@
# internal DNS stub resolver of systemd-resolved. This file lists no search
# domains.
#
-# Run "systemd-resolve --status" to see details about the uplink DNS servers
+# Run "resolvectl status" to see details about the uplink DNS servers
# currently in use.
#
# Third party programs must not access this file directly, but only through the
diff --git a/src/resolve/resolvconf-compat.c b/src/resolve/resolvconf-compat.c
new file mode 100644
index 0000000000..d7e68003e6
--- /dev/null
+++ b/src/resolve/resolvconf-compat.c
@@ -0,0 +1,283 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <getopt.h>
+#include <net/if.h>
+
+#include "alloc-util.h"
+#include "def.h"
+#include "dns-domain.h"
+#include "extract-word.h"
+#include "fileio.h"
+#include "parse-util.h"
+#include "resolvconf-compat.h"
+#include "resolvectl.h"
+#include "resolved-def.h"
+#include "string-util.h"
+#include "strv.h"
+
+static void resolvconf_help(void) {
+ printf("%1$s -a INTERFACE < FILE\n"
+ "%1$s -d INTERFACE\n"
+ "\n"
+ "Register DNS server and domain configuration with systemd-resolved.\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " -a Register per-interface DNS server and domain data\n"
+ " -d Unregister per-interface DNS server and domain data\n"
+ " -f Ignore if specified interface does not exist\n"
+ " -x Send DNS traffic preferably over this interface\n"
+ "\n"
+ "This is a compatibility alias for the resolvectl(1) tool, providing native\n"
+ "command line compatibility with the resolvconf(8) tool of various Linux\n"
+ "distributions and BSD systems. Some options supported by other implementations\n"
+ "are not supported and are ignored: -m, -p. Various options supported by other\n"
+ "implementations are not supported and will cause the invocation to fail: -u,\n"
+ "-I, -i, -l, -R, -r, -v, -V, --enable-updates, --disable-updates,\n"
+ "--updates-are-enabled.\n"
+ , program_invocation_short_name);
+}
+
+static int parse_nameserver(const char *string) {
+ int r;
+
+ assert(string);
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&string, &word, NULL, 0);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ if (strv_push(&arg_set_dns, word) < 0)
+ return log_oom();
+ }
+
+ return 0;
+}
+
+static int parse_search_domain(const char *string) {
+ int r;
+
+ assert(string);
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&string, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ if (strv_push(&arg_set_domain, word) < 0)
+ return log_oom();
+
+ word = NULL;
+ }
+
+ return 0;
+}
+
+int resolvconf_parse_argv(int argc, char *argv[]) {
+
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_ENABLE_UPDATES,
+ ARG_DISABLE_UPDATES,
+ ARG_UPDATES_ARE_ENABLED,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+
+ /* The following are specific to Debian's original resolvconf */
+ { "enable-updates", no_argument, NULL, ARG_ENABLE_UPDATES },
+ { "disable-updates", no_argument, NULL, ARG_DISABLE_UPDATES },
+ { "updates-are-enabled", no_argument, NULL, ARG_UPDATES_ARE_ENABLED },
+ {}
+ };
+
+ enum {
+ TYPE_REGULAR,
+ TYPE_PRIVATE, /* -p: Not supported, treated identically to TYPE_REGULAR */
+ TYPE_EXCLUSIVE, /* -x */
+ } type = TYPE_REGULAR;
+
+ const char *dot, *iface;
+ int c, r;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ /* openresolv checks these environment variables */
+ if (getenv("IF_EXCLUSIVE"))
+ type = TYPE_EXCLUSIVE;
+ if (getenv("IF_PRIVATE"))
+ type = TYPE_PRIVATE; /* not actually supported */
+
+ arg_mode = _MODE_INVALID;
+
+ while ((c = getopt_long(argc, argv, "hadxpfm:uIi:l:Rr:vV", options, NULL)) >= 0)
+ switch(c) {
+
+ case 'h':
+ resolvconf_help();
+ return 0; /* done */;
+
+ case ARG_VERSION:
+ return version();
+
+ /* -a and -d is what everybody can agree on */
+ case 'a':
+ arg_mode = MODE_SET_LINK;
+ break;
+
+ case 'd':
+ arg_mode = MODE_REVERT_LINK;
+ break;
+
+ /* The exclusive/private/force stuff is an openresolv invention, we support in some skewed way */
+ case 'x':
+ type = TYPE_EXCLUSIVE;
+ break;
+
+ case 'p':
+ type = TYPE_PRIVATE; /* not actually supported */
+ break;
+
+ case 'f':
+ arg_ifindex_permissive = true;
+ break;
+
+ /* The metrics stuff is an openresolv invention we ignore (and don't really need) */
+ case 'm':
+ log_debug("Switch -%c ignored.", c);
+ break;
+
+ /* Everybody else can agree on the existance of -u but we don't support it. */
+ case 'u':
+
+ /* The following options are openresolv inventions we don't support. */
+ case 'I':
+ case 'i':
+ case 'l':
+ case 'R':
+ case 'r':
+ case 'v':
+ case 'V':
+ log_error("Switch -%c not supported.", c);
+ return -EINVAL;
+
+ /* The Debian resolvconf commands we don't support. */
+ case ARG_ENABLE_UPDATES:
+ log_error("Switch --enable-updates not supported.");
+ return -EINVAL;
+ case ARG_DISABLE_UPDATES:
+ log_error("Switch --disable-updates not supported.");
+ return -EINVAL;
+ case ARG_UPDATES_ARE_ENABLED:
+ log_error("Switch --updates-are-enabled not supported.");
+ return -EINVAL;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
+ }
+
+ if (arg_mode == _MODE_INVALID) {
+ log_error("Expected either -a or -d on the command line.");
+ return -EINVAL;
+ }
+
+ if (optind+1 != argc) {
+ log_error("Expected interface name as argument.");
+ return -EINVAL;
+ }
+
+ dot = strchr(argv[optind], '.');
+ if (dot) {
+ iface = strndupa(argv[optind], dot - argv[optind]);
+ log_debug("Ignoring protocol specifier '%s'.", dot + 1);
+ } else
+ iface = argv[optind];
+ optind++;
+
+ if (parse_ifindex(iface, &arg_ifindex) < 0) {
+ int ifi;
+
+ ifi = if_nametoindex(iface);
+ if (ifi <= 0) {
+ if (errno == ENODEV && arg_ifindex_permissive) {
+ log_debug("Interface '%s' not found, but -f specified, ignoring.", iface);
+ return 0; /* done */
+ }
+
+ return log_error_errno(errno, "Unknown interface '%s': %m", iface);
+ }
+
+ arg_ifindex = ifi;
+ arg_ifname = iface;
+ }
+
+ if (arg_mode == MODE_SET_LINK) {
+ unsigned n = 0;
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ const char *a, *l;
+
+ r = read_line(stdin, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read from stdin: %m");
+ if (r == 0)
+ break;
+
+ n++;
+
+ l = strstrip(line);
+ if (IN_SET(*l, '#', ';', 0))
+ continue;
+
+ a = first_word(l, "nameserver");
+ if (a) {
+ (void) parse_nameserver(a);
+ continue;
+ }
+
+ a = first_word(l, "domain");
+ if (!a)
+ a = first_word(l, "search");
+ if (a) {
+ (void) parse_search_domain(a);
+ continue;
+ }
+
+ log_syntax(NULL, LOG_DEBUG, "stdin", n, 0, "Ignoring resolv.conf line: %s", l);
+ }
+
+ if (type == TYPE_EXCLUSIVE) {
+
+ /* If -x mode is selected, let's preferably route non-suffixed lookups to this interface. This
+ * somewhat matches the original -x behaviour */
+
+ r = strv_extend(&arg_set_domain, "~.");
+ if (r < 0)
+ return log_oom();
+
+ } else if (type == TYPE_PRIVATE)
+ log_debug("Private DNS server data not supported, ignoring.");
+
+ if (!arg_set_dns) {
+ log_error("No DNS servers specified, refusing operation.");
+ return -EINVAL;
+ }
+ }
+
+ return 1; /* work to do */
+}
diff --git a/src/resolve/resolvconf-compat.h b/src/resolve/resolvconf-compat.h
new file mode 100644
index 0000000000..507ac3d222
--- /dev/null
+++ b/src/resolve/resolvconf-compat.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+int resolvconf_parse_argv(int argc, char *argv[]);
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolvectl.c
index d7515721b6..e96c13fea6 100644
--- a/src/resolve/resolve-tool.c
+++ b/src/resolve/resolvectl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
#include <net/if.h>
@@ -36,26 +18,25 @@
#include "netlink-util.h"
#include "pager.h"
#include "parse-util.h"
+#include "resolvconf-compat.h"
+#include "resolvectl.h"
#include "resolved-def.h"
#include "resolved-dns-packet.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
+#include "verbs.h"
static int arg_family = AF_UNSPEC;
-static int arg_ifindex = 0;
+int arg_ifindex = 0;
+const char *arg_ifname = NULL;
static uint16_t arg_type = 0;
static uint16_t arg_class = 0;
static bool arg_legend = true;
static uint64_t arg_flags = 0;
static bool arg_no_pager = false;
-
-typedef enum ServiceFamily {
- SERVICE_FAMILY_TCP,
- SERVICE_FAMILY_UDP,
- SERVICE_FAMILY_SCTP,
- _SERVICE_FAMILY_INVALID = -1,
-} ServiceFamily;
-static ServiceFamily arg_service_family = SERVICE_FAMILY_TCP;
+bool arg_ifindex_permissive = false; /* If true, don't generate an error if the specified interface index doesn't exist */
+static const char *arg_service_family = NULL;
typedef enum RawType {
RAW_NONE,
@@ -64,50 +45,39 @@ typedef enum RawType {
} RawType;
static RawType arg_raw = RAW_NONE;
-static enum {
- MODE_RESOLVE_HOST,
- MODE_RESOLVE_RECORD,
- MODE_RESOLVE_SERVICE,
- MODE_RESOLVE_OPENPGP,
- MODE_RESOLVE_TLSA,
- MODE_STATISTICS,
- MODE_RESET_STATISTICS,
- MODE_FLUSH_CACHES,
- MODE_RESET_SERVER_FEATURES,
- MODE_STATUS,
- MODE_SET_LINK,
- MODE_REVERT_LINK,
-} arg_mode = MODE_RESOLVE_HOST;
-
-static struct in_addr_data *arg_set_dns = NULL;
-static size_t arg_n_set_dns = 0;
-static char **arg_set_domain = NULL;
-static char *arg_set_llmnr = NULL;
-static char *arg_set_mdns = NULL;
-static char *arg_set_dnssec = NULL;
-static char **arg_set_nta = NULL;
+ExecutionMode arg_mode = MODE_RESOLVE_HOST;
-static ServiceFamily service_family_from_string(const char *s) {
- if (!s || streq(s, "tcp"))
- return SERVICE_FAMILY_TCP;
- if (streq(s, "udp"))
- return SERVICE_FAMILY_UDP;
- if (streq(s, "sctp"))
- return SERVICE_FAMILY_SCTP;
- return _SERVICE_FAMILY_INVALID;
-}
+char **arg_set_dns = NULL;
+char **arg_set_domain = NULL;
+static const char *arg_set_llmnr = NULL;
+static const char *arg_set_mdns = NULL;
+static const char *arg_set_dns_over_tls = NULL;
+static const char *arg_set_dnssec = NULL;
+static char **arg_set_nta = NULL;
-static const char* service_family_to_string(ServiceFamily service) {
- switch(service) {
- case SERVICE_FAMILY_TCP:
- return "_tcp";
- case SERVICE_FAMILY_UDP:
- return "_udp";
- case SERVICE_FAMILY_SCTP:
- return "_sctp";
- default:
- assert_not_reached("invalid service");
+typedef enum StatusMode {
+ STATUS_ALL,
+ STATUS_DNS,
+ STATUS_DOMAIN,
+ STATUS_LLMNR,
+ STATUS_MDNS,
+ STATUS_PRIVATE,
+ STATUS_DNSSEC,
+ STATUS_NTA,
+} StatusMode;
+
+static int parse_ifindex_with_warn(const char *s) {
+ int ifi;
+
+ assert(s);
+
+ if (parse_ifindex(s, &ifi) < 0) {
+ ifi = if_nametoindex(s);
+ if (ifi <= 0)
+ return log_error_errno(errno, "Unknown interface %s: %m", s);
}
+
+ return ifi;
}
static void print_source(uint64_t flags, usec_t rtt) {
@@ -140,7 +110,6 @@ static void print_source(uint64_t flags, usec_t rtt) {
}
static int resolve_host(sd_bus *bus, const char *name) {
-
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *canonical = NULL;
@@ -639,6 +608,39 @@ invalid:
return -EINVAL;
}
+static int verb_query(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
+ char **p;
+ int q, r = 0;
+
+ if (arg_type != 0)
+ STRV_FOREACH(p, argv + 1) {
+ q = resolve_record(bus, *p, arg_class, arg_type, true);
+ if (q < 0)
+ r = q;
+ }
+
+ else
+ STRV_FOREACH(p, argv + 1) {
+ if (startswith(*p, "dns:"))
+ q = resolve_rfc4501(bus, *p);
+ else {
+ int family, ifindex;
+ union in_addr_union a;
+
+ q = in_addr_ifindex_from_string_auto(*p, &family, &a, &ifindex);
+ if (q >= 0)
+ q = resolve_address(bus, family, &a, ifindex);
+ else
+ q = resolve_host(bus, *p);
+ }
+ if (q < 0)
+ r = q;
+ }
+
+ return r;
+}
+
static int resolve_service(sd_bus *bus, const char *name, const char *type, const char *domain) {
const char *canonical_name, *canonical_type, *canonical_domain;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
@@ -834,6 +836,17 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons
return 0;
}
+static int verb_service(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
+
+ if (argc == 2)
+ return resolve_service(bus, NULL, NULL, argv[1]);
+ else if (argc == 3)
+ return resolve_service(bus, NULL, argv[1], argv[2]);
+ else
+ return resolve_service(bus, argv[1], argv[2], argv[3]);
+}
+
static int resolve_openpgp(sd_bus *bus, const char *address) {
const char *domain, *full;
int r;
@@ -882,7 +895,21 @@ static int resolve_openpgp(sd_bus *bus, const char *address) {
return r;
}
-static int resolve_tlsa(sd_bus *bus, const char *address) {
+static int verb_openpgp(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
+ char **p;
+ int q, r = 0;
+
+ STRV_FOREACH(p, argv + 1) {
+ q = resolve_openpgp(bus, *p);
+ if (q < 0)
+ r = q;
+ }
+
+ return r;
+}
+
+static int resolve_tlsa(sd_bus *bus, const char *family, const char *address) {
const char *port;
uint16_t port_num = 443;
_cleanup_free_ char *full = NULL;
@@ -900,9 +927,9 @@ static int resolve_tlsa(sd_bus *bus, const char *address) {
address = strndupa(address, port - address);
}
- r = asprintf(&full, "_%u.%s.%s",
+ r = asprintf(&full, "_%u._%s.%s",
port_num,
- service_family_to_string(arg_service_family),
+ family,
address);
if (r < 0)
return log_oom();
@@ -914,9 +941,34 @@ static int resolve_tlsa(sd_bus *bus, const char *address) {
arg_type ?: DNS_TYPE_TLSA, true);
}
-static int show_statistics(sd_bus *bus) {
+static bool service_family_is_valid(const char *s) {
+ return STR_IN_SET(s, "tcp", "udp", "sctp");
+}
+
+static int verb_tlsa(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
+ char **p, **args = argv + 1;
+ const char *family = "tcp";
+ int q, r = 0;
+
+ if (service_family_is_valid(argv[1])) {
+ family = argv[1];
+ args++;
+ }
+
+ STRV_FOREACH(p, args) {
+ q = resolve_tlsa(bus, family, *p);
+ if (q < 0)
+ r = q;
+ }
+
+ return r;
+}
+
+static int show_statistics(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ sd_bus *bus = userdata;
uint64_t n_current_transactions, n_total_transactions,
cache_size, n_cache_hit, n_cache_miss,
n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate;
@@ -1031,8 +1083,9 @@ static int show_statistics(sd_bus *bus) {
return 0;
}
-static int reset_statistics(sd_bus *bus) {
+static int reset_statistics(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
r = sd_bus_call_method(bus,
@@ -1049,8 +1102,9 @@ static int reset_statistics(sd_bus *bus) {
return 0;
}
-static int flush_caches(sd_bus *bus) {
+static int flush_caches(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
r = sd_bus_call_method(bus,
@@ -1067,8 +1121,9 @@ static int flush_caches(sd_bus *bus) {
return 0;
}
-static int reset_server_features(sd_bus *bus) {
+static int reset_server_features(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
r = sd_bus_call_method(bus,
@@ -1085,6 +1140,66 @@ static int reset_server_features(sd_bus *bus) {
return 0;
}
+static int read_dns_server_one(sd_bus_message *m, bool with_ifindex, char **ret) {
+ _cleanup_free_ char *pretty = NULL;
+ int ifindex, family, r;
+ const void *a;
+ size_t sz;
+
+ assert(m);
+ assert(ret);
+
+ r = sd_bus_message_enter_container(m, 'r', with_ifindex ? "iiay" : "iay");
+ if (r <= 0)
+ return r;
+
+ if (with_ifindex) {
+ r = sd_bus_message_read(m, "i", &ifindex);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_read(m, "i", &family);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read_array(m, 'y', &a, &sz);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ if (with_ifindex && ifindex != 0) {
+ /* only show the global ones here */
+ *ret = NULL;
+ return 1;
+ }
+
+ if (!IN_SET(family, AF_INET, AF_INET6)) {
+ log_debug("Unexpected family, ignoring: %i", family);
+
+ *ret = NULL;
+ return 1;
+ }
+
+ if (sz != FAMILY_ADDRESS_SIZE(family)) {
+ log_debug("Address size mismatch, ignoring.");
+
+ *ret = NULL;
+ return 1;
+ }
+
+ r = in_addr_to_string(family, a, &pretty);
+ if (r < 0)
+ return r;
+
+ *ret = TAKE_PTR(pretty);
+
+ return 1;
+}
+
static int map_link_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
char ***l = userdata;
int r;
@@ -1099,42 +1214,16 @@ static int map_link_dns_servers(sd_bus *bus, const char *member, sd_bus_message
return r;
for (;;) {
- const void *a;
- char *pretty;
- int family;
- size_t sz;
+ char *pretty = NULL;
- r = sd_bus_message_enter_container(m, 'r', "iay");
+ r = read_dns_server_one(m, false, &pretty);
if (r < 0)
return r;
if (r == 0)
break;
- r = sd_bus_message_read(m, "i", &family);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read_array(m, 'y', &a, &sz);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- if (!IN_SET(family, AF_INET, AF_INET6)) {
- log_debug("Unexpected family, ignoring.");
+ if (isempty(pretty))
continue;
- }
-
- if (sz != FAMILY_ADDRESS_SIZE(family)) {
- log_debug("Address size mismatch, ignoring.");
- continue;
- }
-
- r = in_addr_to_string(family, a, &pretty);
- if (r < 0)
- return r;
r = strv_consume(l, pretty);
if (r < 0)
@@ -1148,6 +1237,46 @@ static int map_link_dns_servers(sd_bus *bus, const char *member, sd_bus_message
return 0;
}
+static int map_link_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ assert(m);
+ assert(userdata);
+
+ return read_dns_server_one(m, false, userdata);
+}
+
+static int read_domain_one(sd_bus_message *m, bool with_ifindex, char **ret) {
+ _cleanup_free_ char *str = NULL;
+ int ifindex, route_only, r;
+ const char *domain;
+
+ assert(m);
+ assert(ret);
+
+ if (with_ifindex)
+ r = sd_bus_message_read(m, "(isb)", &ifindex, &domain, &route_only);
+ else
+ r = sd_bus_message_read(m, "(sb)", &domain, &route_only);
+ if (r <= 0)
+ return r;
+
+ if (with_ifindex && ifindex != 0) {
+ /* only show the global ones here */
+ *ret = NULL;
+ return 1;
+ }
+
+ if (route_only)
+ str = strappend("~", domain);
+ else
+ str = strdup(domain);
+ if (!str)
+ return -ENOMEM;
+
+ *ret = TAKE_PTR(str);
+
+ return 1;
+}
+
static int map_link_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
char ***l = userdata;
int r;
@@ -1162,22 +1291,16 @@ static int map_link_domains(sd_bus *bus, const char *member, sd_bus_message *m,
return r;
for (;;) {
- const char *domain;
- int route_only;
- char *pretty;
+ char *pretty = NULL;
- r = sd_bus_message_read(m, "(sb)", &domain, &route_only);
+ r = read_domain_one(m, false, &pretty);
if (r < 0)
return r;
if (r == 0)
break;
- if (route_only)
- pretty = strappend("~", domain);
- else
- pretty = strdup(domain);
- if (!pretty)
- return -ENOMEM;
+ if (isempty(pretty))
+ continue;
r = strv_consume(l, pretty);
if (r < 0)
@@ -1191,32 +1314,51 @@ static int map_link_domains(sd_bus *bus, const char *member, sd_bus_message *m,
return 0;
}
-static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empty_line) {
+static int status_print_strv_ifindex(int ifindex, const char *ifname, char **p) {
+ char **i;
+
+ printf("%sLink %i (%s)%s:",
+ ansi_highlight(), ifindex, ifname, ansi_normal());
+
+ STRV_FOREACH(i, p)
+ printf(" %s", *i);
+
+ printf("\n");
+
+ return 0;
+}
+
+static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode mode, bool *empty_line) {
struct link_info {
uint64_t scopes_mask;
- char *llmnr;
- char *mdns;
- char *dnssec;
+ const char *llmnr;
+ const char *mdns;
+ const char *dns_over_tls;
+ const char *dnssec;
+ char *current_dns;
char **dns;
char **domains;
char **ntas;
- int dnssec_supported;
+ bool dnssec_supported;
} link_info = {};
static const struct bus_properties_map property_map[] = {
- { "ScopesMask", "t", NULL, offsetof(struct link_info, scopes_mask) },
- { "DNS", "a(iay)", map_link_dns_servers, offsetof(struct link_info, dns) },
- { "Domains", "a(sb)", map_link_domains, offsetof(struct link_info, domains) },
- { "LLMNR", "s", NULL, offsetof(struct link_info, llmnr) },
- { "MulticastDNS", "s", NULL, offsetof(struct link_info, mdns) },
- { "DNSSEC", "s", NULL, offsetof(struct link_info, dnssec) },
- { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct link_info, ntas) },
- { "DNSSECSupported", "b", NULL, offsetof(struct link_info, dnssec_supported) },
+ { "ScopesMask", "t", NULL, offsetof(struct link_info, scopes_mask) },
+ { "DNS", "a(iay)", map_link_dns_servers, offsetof(struct link_info, dns) },
+ { "CurrentDNSServer", "(iay)", map_link_current_dns_server, offsetof(struct link_info, current_dns) },
+ { "Domains", "a(sb)", map_link_domains, offsetof(struct link_info, domains) },
+ { "LLMNR", "s", NULL, offsetof(struct link_info, llmnr) },
+ { "MulticastDNS", "s", NULL, offsetof(struct link_info, mdns) },
+ { "DNSOverTLS", "s", NULL, offsetof(struct link_info, dns_over_tls) },
+ { "DNSSEC", "s", NULL, offsetof(struct link_info, dnssec) },
+ { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct link_info, ntas) },
+ { "DNSSECSupported", "b", NULL, offsetof(struct link_info, dnssec_supported) },
{}
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *ifi = NULL, *p = NULL;
char ifname[IF_NAMESIZE] = "";
char **i;
@@ -1224,7 +1366,6 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt
assert(bus);
assert(ifindex > 0);
- assert(empty_line);
if (!name) {
if (!if_indextoname(ifindex, ifname))
@@ -1244,16 +1385,69 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt
"org.freedesktop.resolve1",
p,
property_map,
+ BUS_MAP_BOOLEAN_AS_BOOL,
&error,
+ &m,
&link_info);
if (r < 0) {
log_error_errno(r, "Failed to get link data for %i: %s", ifindex, bus_error_message(&error, r));
goto finish;
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
+
+ if (mode == STATUS_DNS) {
+ r = status_print_strv_ifindex(ifindex, name, link_info.dns);
+ goto finish;
+ }
+
+ if (mode == STATUS_DOMAIN) {
+ r = status_print_strv_ifindex(ifindex, name, link_info.domains);
+ goto finish;
+ }
+
+ if (mode == STATUS_NTA) {
+ r = status_print_strv_ifindex(ifindex, name, link_info.ntas);
+ goto finish;
+ }
+
+ if (mode == STATUS_LLMNR) {
+ printf("%sLink %i (%s)%s: %s\n",
+ ansi_highlight(), ifindex, name, ansi_normal(),
+ strna(link_info.llmnr));
+
+ r = 0;
+ goto finish;
+ }
+
+ if (mode == STATUS_MDNS) {
+ printf("%sLink %i (%s)%s: %s\n",
+ ansi_highlight(), ifindex, name, ansi_normal(),
+ strna(link_info.mdns));
- if (*empty_line)
+ r = 0;
+ goto finish;
+ }
+
+ if (mode == STATUS_PRIVATE) {
+ printf("%sLink %i (%s)%s: %s\n",
+ ansi_highlight(), ifindex, name, ansi_normal(),
+ strna(link_info.dns_over_tls));
+
+ r = 0;
+ goto finish;
+ }
+
+ if (mode == STATUS_DNSSEC) {
+ printf("%sLink %i (%s)%s: %s\n",
+ ansi_highlight(), ifindex, name, ansi_normal(),
+ strna(link_info.dnssec));
+
+ r = 0;
+ goto finish;
+ }
+
+ if (empty_line && *empty_line)
fputc('\n', stdout);
printf("%sLink %i (%s)%s\n",
@@ -1271,13 +1465,18 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt
printf(" LLMNR setting: %s\n"
"MulticastDNS setting: %s\n"
+ " DNSOverTLS setting: %s\n"
" DNSSEC setting: %s\n"
" DNSSEC supported: %s\n",
strna(link_info.llmnr),
strna(link_info.mdns),
+ strna(link_info.dns_over_tls),
strna(link_info.dnssec),
yes_no(link_info.dnssec_supported));
+ if (link_info.current_dns)
+ printf(" Current DNS Server: %s\n", link_info.current_dns);
+
STRV_FOREACH(i, link_info.dns) {
printf(" %s %s\n",
i == link_info.dns ? "DNS Servers:" : " ",
@@ -1296,16 +1495,15 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt
*i);
}
- *empty_line = true;
+ if (empty_line)
+ *empty_line = true;
r = 0;
finish:
+ free(link_info.current_dns);
strv_free(link_info.dns);
strv_free(link_info.domains);
- free(link_info.llmnr);
- free(link_info.mdns);
- free(link_info.dnssec);
strv_free(link_info.ntas);
return r;
}
@@ -1324,46 +1522,17 @@ static int map_global_dns_servers(sd_bus *bus, const char *member, sd_bus_messag
return r;
for (;;) {
- const void *a;
- char *pretty;
- int family, ifindex;
- size_t sz;
+ char *pretty = NULL;
- r = sd_bus_message_enter_container(m, 'r', "iiay");
+ r = read_dns_server_one(m, true, &pretty);
if (r < 0)
return r;
if (r == 0)
break;
- r = sd_bus_message_read(m, "ii", &ifindex, &family);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read_array(m, 'y', &a, &sz);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- if (ifindex != 0) /* only show the global ones here */
+ if (isempty(pretty))
continue;
- if (!IN_SET(family, AF_INET, AF_INET6)) {
- log_debug("Unexpected family, ignoring.");
- continue;
- }
-
- if (sz != FAMILY_ADDRESS_SIZE(family)) {
- log_debug("Address size mismatch, ignoring.");
- continue;
- }
-
- r = in_addr_to_string(family, a, &pretty);
- if (r < 0)
- return r;
-
r = strv_consume(l, pretty);
if (r < 0)
return r;
@@ -1376,6 +1545,13 @@ static int map_global_dns_servers(sd_bus *bus, const char *member, sd_bus_messag
return 0;
}
+static int map_global_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ assert(m);
+ assert(userdata);
+
+ return read_dns_server_one(m, true, userdata);
+}
+
static int map_global_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
char ***l = userdata;
int r;
@@ -1390,26 +1566,17 @@ static int map_global_domains(sd_bus *bus, const char *member, sd_bus_message *m
return r;
for (;;) {
- const char *domain;
- int route_only, ifindex;
- char *pretty;
+ char *pretty = NULL;
- r = sd_bus_message_read(m, "(isb)", &ifindex, &domain, &route_only);
+ r = read_domain_one(m, true, &pretty);
if (r < 0)
return r;
if (r == 0)
break;
- if (ifindex != 0) /* only show the global ones here */
+ if (isempty(pretty))
continue;
- if (route_only)
- pretty = strappend("~", domain);
- else
- pretty = strdup(domain);
- if (!pretty)
- return -ENOMEM;
-
r = strv_consume(l, pretty);
if (r < 0)
return r;
@@ -1422,22 +1589,50 @@ static int map_global_domains(sd_bus *bus, const char *member, sd_bus_message *m
return 0;
}
-static int status_global(sd_bus *bus, bool *empty_line) {
+static int status_print_strv_global(char **p) {
+ char **i;
+
+ printf("%sGlobal%s:", ansi_highlight(), ansi_normal());
+
+ STRV_FOREACH(i, p)
+ printf(" %s", *i);
+
+ printf("\n");
+
+ return 0;
+}
+
+static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
struct global_info {
+ char *current_dns;
char **dns;
+ char **fallback_dns;
char **domains;
char **ntas;
+ const char *llmnr;
+ const char *mdns;
+ const char *dns_over_tls;
+ const char *dnssec;
+ bool dnssec_supported;
} global_info = {};
static const struct bus_properties_map property_map[] = {
- { "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) },
- { "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) },
- { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) },
+ { "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) },
+ { "FallbackDNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, fallback_dns) },
+ { "CurrentDNSServer", "(iiay)", map_global_current_dns_server, offsetof(struct global_info, current_dns) },
+ { "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) },
+ { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) },
+ { "LLMNR", "s", NULL, offsetof(struct global_info, llmnr) },
+ { "MulticastDNS", "s", NULL, offsetof(struct global_info, mdns) },
+ { "DNSOverTLS", "s", NULL, offsetof(struct global_info, dns_over_tls) },
+ { "DNSSEC", "s", NULL, offsetof(struct global_info, dnssec) },
+ { "DNSSECSupported", "b", NULL, offsetof(struct global_info, dnssec_supported) },
{}
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
char **i;
int r;
@@ -1448,27 +1643,92 @@ static int status_global(sd_bus *bus, bool *empty_line) {
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
property_map,
+ BUS_MAP_BOOLEAN_AS_BOOL,
&error,
+ &m,
&global_info);
if (r < 0) {
log_error_errno(r, "Failed to get global data: %s", bus_error_message(&error, r));
goto finish;
}
- if (strv_isempty(global_info.dns) && strv_isempty(global_info.domains) && strv_isempty(global_info.ntas)) {
+ (void) pager_open(arg_no_pager, false);
+
+ if (mode == STATUS_DNS) {
+ r = status_print_strv_global(global_info.dns);
+ goto finish;
+ }
+
+ if (mode == STATUS_DOMAIN) {
+ r = status_print_strv_global(global_info.domains);
+ goto finish;
+ }
+
+ if (mode == STATUS_NTA) {
+ r = status_print_strv_global(global_info.ntas);
+ goto finish;
+ }
+
+ if (mode == STATUS_LLMNR) {
+ printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
+ strna(global_info.llmnr));
+
+ r = 0;
+ goto finish;
+ }
+
+ if (mode == STATUS_MDNS) {
+ printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
+ strna(global_info.mdns));
+
r = 0;
goto finish;
}
- pager_open(arg_no_pager, false);
+ if (mode == STATUS_PRIVATE) {
+ printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
+ strna(global_info.dns_over_tls));
+
+ r = 0;
+ goto finish;
+ }
+
+ if (mode == STATUS_DNSSEC) {
+ printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
+ strna(global_info.dnssec));
+
+ r = 0;
+ goto finish;
+ }
printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
+
+ printf(" LLMNR setting: %s\n"
+ "MulticastDNS setting: %s\n"
+ " DNSOverTLS setting: %s\n"
+ " DNSSEC setting: %s\n"
+ " DNSSEC supported: %s\n",
+ strna(global_info.llmnr),
+ strna(global_info.mdns),
+ strna(global_info.dns_over_tls),
+ strna(global_info.dnssec),
+ yes_no(global_info.dnssec_supported));
+
+ if (global_info.current_dns)
+ printf(" Current DNS Server: %s\n", global_info.current_dns);
+
STRV_FOREACH(i, global_info.dns) {
printf(" %s %s\n",
i == global_info.dns ? "DNS Servers:" : " ",
*i);
}
+ STRV_FOREACH(i, global_info.fallback_dns) {
+ printf("%s %s\n",
+ i == global_info.fallback_dns ? "Fallback DNS Servers:" : " ",
+ *i);
+ }
+
STRV_FOREACH(i, global_info.domains) {
printf(" %s %s\n",
i == global_info.domains ? "DNS Domain:" : " ",
@@ -1487,14 +1747,16 @@ static int status_global(sd_bus *bus, bool *empty_line) {
r = 0;
finish:
+ free(global_info.current_dns);
strv_free(global_info.dns);
+ strv_free(global_info.fallback_dns);
strv_free(global_info.domains);
strv_free(global_info.ntas);
return r;
}
-static int status_all(sd_bus *bus) {
+static int status_all(sd_bus *bus, StatusMode mode) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
sd_netlink_message *i;
@@ -1503,7 +1765,7 @@ static int status_all(sd_bus *bus) {
assert(bus);
- r = status_global(bus, &empty_line);
+ r = status_global(bus, mode, &empty_line);
if (r < 0)
return r;
@@ -1547,7 +1809,7 @@ static int status_all(sd_bus *bus) {
if (q < 0)
return rtnl_log_parse_error(q);
- q = status_ifindex(bus, ifindex, name, &empty_line);
+ q = status_ifindex(bus, ifindex, name, mode, &empty_line);
if (q < 0 && r >= 0)
r = q;
}
@@ -1555,220 +1817,462 @@ static int status_all(sd_bus *bus) {
return r;
}
-static int set_link(sd_bus *bus) {
+static int verb_status(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
+ int q, r = 0;
+
+ if (argc > 1) {
+ char **ifname;
+ bool empty_line = false;
+
+ STRV_FOREACH(ifname, argv + 1) {
+ int ifindex;
+
+ ifindex = parse_ifindex_with_warn(*ifname);
+ if (ifindex < 0)
+ continue;
+
+ q = status_ifindex(bus, ifindex, NULL, STATUS_ALL, &empty_line);
+ if (q < 0)
+ r = q;
+ }
+ } else
+ r = status_all(bus, STATUS_ALL);
+
+ return r;
+}
+
+static int log_interface_is_managed(int r, int ifindex) {
+ char ifname[IFNAMSIZ];
+
+ return log_error_errno(r,
+ "The specified interface %s is managed by systemd-networkd. Operation refused.\n"
+ "Please configure DNS settings for systemd-networkd managed interfaces directly in their .network files.",
+ strna(if_indextoname(ifindex, ifname)));
+}
+
+static int verb_dns(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r = 0, q;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
+ sd_bus *bus = userdata;
+ int ifindex, r;
+ char **p;
assert(bus);
- if (arg_n_set_dns > 0) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
- size_t i;
+ if (argc <= 1)
+ return status_all(bus, STATUS_DNS);
- q = sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "SetLinkDNS");
- if (q < 0)
- return bus_log_create_error(q);
+ ifindex = parse_ifindex_with_warn(argv[1]);
+ if (ifindex < 0)
+ return ifindex;
- q = sd_bus_message_append(req, "i", arg_ifindex);
- if (q < 0)
- return bus_log_create_error(q);
+ if (ifindex == LOOPBACK_IFINDEX) {
+ log_error("Interface can't be the loopback interface (lo). Sorry.");
+ return -EINVAL;
+ }
- q = sd_bus_message_open_container(req, 'a', "(iay)");
- if (q < 0)
- return bus_log_create_error(q);
+ if (argc == 2)
+ return status_ifindex(bus, ifindex, NULL, STATUS_DNS, NULL);
- for (i = 0; i < arg_n_set_dns; i++) {
- q = sd_bus_message_open_container(req, 'r', "iay");
- if (q < 0)
- return bus_log_create_error(q);
+ r = sd_bus_message_new_method_call(
+ bus,
+ &req,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkDNS");
+ if (r < 0)
+ return bus_log_create_error(r);
- q = sd_bus_message_append(req, "i", arg_set_dns[i].family);
- if (q < 0)
- return bus_log_create_error(q);
+ r = sd_bus_message_append(req, "i", ifindex);
+ if (r < 0)
+ return bus_log_create_error(r);
- q = sd_bus_message_append_array(req, 'y', &arg_set_dns[i].address, FAMILY_ADDRESS_SIZE(arg_set_dns[i].family));
- if (q < 0)
- return bus_log_create_error(q);
+ r = sd_bus_message_open_container(req, 'a', "(iay)");
+ if (r < 0)
+ return bus_log_create_error(r);
- q = sd_bus_message_close_container(req);
- if (q < 0)
- return bus_log_create_error(q);
- }
+ STRV_FOREACH(p, argv + 2) {
+ struct in_addr_data data;
- q = sd_bus_message_close_container(req);
- if (q < 0)
- return bus_log_create_error(q);
+ r = in_addr_from_string_auto(*p, &data.family, &data.address);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse DNS server address: %s", *p);
- q = sd_bus_call(bus, req, 0, &error, NULL);
- if (q < 0) {
- if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
- goto is_managed;
+ r = sd_bus_message_open_container(req, 'r', "iay");
+ if (r < 0)
+ return bus_log_create_error(r);
- log_error_errno(q, "Failed to set DNS configuration: %s", bus_error_message(&error, q));
- if (r == 0)
- r = q;
- }
+ r = sd_bus_message_append(req, "i", data.family);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_array(req, 'y', &data.address, FAMILY_ADDRESS_SIZE(data.family));
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_close_container(req);
+ if (r < 0)
+ return bus_log_create_error(r);
}
- if (!strv_isempty(arg_set_domain)) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
- char **p;
+ r = sd_bus_message_close_container(req);
+ if (r < 0)
+ return bus_log_create_error(r);
- q = sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "SetLinkDomains");
- if (q < 0)
- return bus_log_create_error(q);
+ r = sd_bus_call(bus, req, 0, &error, NULL);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
+ return log_interface_is_managed(r, ifindex);
- q = sd_bus_message_append(req, "i", arg_ifindex);
- if (q < 0)
- return bus_log_create_error(q);
+ if (arg_ifindex_permissive &&
+ sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
+ return 0;
- q = sd_bus_message_open_container(req, 'a', "(sb)");
- if (q < 0)
- return bus_log_create_error(q);
+ return log_error_errno(r, "Failed to set DNS configuration: %s", bus_error_message(&error, r));
+ }
+
+ return 0;
+}
- STRV_FOREACH(p, arg_set_domain) {
- const char *n;
+static int verb_domain(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
+ sd_bus *bus = userdata;
+ int ifindex, r;
+ char **p;
- n = **p == '~' ? *p + 1 : *p;
- q = sd_bus_message_append(req, "(sb)", n, **p == '~');
- if (q < 0)
- return bus_log_create_error(q);
- }
+ assert(bus);
- q = sd_bus_message_close_container(req);
- if (q < 0)
- return bus_log_create_error(q);
+ if (argc <= 1)
+ return status_all(bus, STATUS_DOMAIN);
- q = sd_bus_call(bus, req, 0, &error, NULL);
- if (q < 0) {
- if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
- goto is_managed;
+ ifindex = parse_ifindex_with_warn(argv[1]);
+ if (ifindex < 0)
+ return ifindex;
- log_error_errno(q, "Failed to set domain configuration: %s", bus_error_message(&error, q));
- if (r == 0)
- r = q;
- }
+ if (ifindex == LOOPBACK_IFINDEX) {
+ log_error("Interface can't be the loopback interface (lo). Sorry.");
+ return -EINVAL;
}
- if (arg_set_llmnr) {
- q = sd_bus_call_method(bus,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "SetLinkLLMNR",
- &error,
- NULL,
- "is", arg_ifindex, arg_set_llmnr);
- if (q < 0) {
- if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
- goto is_managed;
-
- log_error_errno(q, "Failed to set LLMNR configuration: %s", bus_error_message(&error, q));
- if (r == 0)
- r = q;
+ if (argc == 2)
+ return status_ifindex(bus, ifindex, NULL, STATUS_DOMAIN, NULL);
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &req,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkDomains");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(req, "i", ifindex);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(req, 'a', "(sb)");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ STRV_FOREACH(p, argv + 2) {
+ const char *n;
+
+ n = **p == '~' ? *p + 1 : *p;
+
+ r = dns_name_is_valid(n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to validate specified domain %s: %m", n);
+ if (r == 0) {
+ log_error("Domain not valid: %s", n);
+ return -EINVAL;
}
+
+ r = sd_bus_message_append(req, "(sb)", n, **p == '~');
+ if (r < 0)
+ return bus_log_create_error(r);
}
- if (arg_set_mdns) {
- q = sd_bus_call_method(bus,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "SetLinkMulticastDNS",
- &error,
- NULL,
- "is", arg_ifindex, arg_set_mdns);
- if (q < 0) {
- if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
- goto is_managed;
-
- log_error_errno(q, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error, q));
- if (r == 0)
- r = q;
- }
+ r = sd_bus_message_close_container(req);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, req, 0, &error, NULL);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
+ return log_interface_is_managed(r, ifindex);
+
+ if (arg_ifindex_permissive &&
+ sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
+ return 0;
+
+ return log_error_errno(r, "Failed to set domain configuration: %s", bus_error_message(&error, r));
}
- if (arg_set_dnssec) {
- q = sd_bus_call_method(bus,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "SetLinkDNSSEC",
- &error,
- NULL,
- "is", arg_ifindex, arg_set_dnssec);
- if (q < 0) {
- if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
- goto is_managed;
-
- log_error_errno(q, "Failed to set DNSSEC configuration: %s", bus_error_message(&error, q));
- if (r == 0)
- r = q;
- }
+ return 0;
+}
+
+static int verb_llmnr(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
+ int ifindex, r;
+
+ assert(bus);
+
+ if (argc <= 1)
+ return status_all(bus, STATUS_LLMNR);
+
+ ifindex = parse_ifindex_with_warn(argv[1]);
+ if (ifindex < 0)
+ return ifindex;
+
+ if (ifindex == LOOPBACK_IFINDEX) {
+ log_error("Interface can't be the loopback interface (lo). Sorry.");
+ return -EINVAL;
}
- if (!strv_isempty(arg_set_nta)) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
+ if (argc == 2)
+ return status_ifindex(bus, ifindex, NULL, STATUS_LLMNR, NULL);
- q = sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "SetLinkDNSSECNegativeTrustAnchors");
- if (q < 0)
- return bus_log_create_error(q);
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkLLMNR",
+ &error,
+ NULL,
+ "is", ifindex, argv[2]);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
+ return log_interface_is_managed(r, ifindex);
- q = sd_bus_message_append(req, "i", arg_ifindex);
- if (q < 0)
- return bus_log_create_error(q);
+ if (arg_ifindex_permissive &&
+ sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
+ return 0;
- q = sd_bus_message_append_strv(req, arg_set_nta);
- if (q < 0)
- return bus_log_create_error(q);
+ return log_error_errno(r, "Failed to set LLMNR configuration: %s", bus_error_message(&error, r));
+ }
+
+ return 0;
+}
+
+static int verb_mdns(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
+ int ifindex, r;
- q = sd_bus_call(bus, req, 0, &error, NULL);
- if (q < 0) {
- if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
- goto is_managed;
+ assert(bus);
- log_error_errno(q, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error, q));
- if (r == 0)
- r = q;
+ if (argc <= 1)
+ return status_all(bus, STATUS_MDNS);
+
+ ifindex = parse_ifindex_with_warn(argv[1]);
+ if (ifindex < 0)
+ return ifindex;
+
+ if (ifindex == LOOPBACK_IFINDEX) {
+ log_error("Interface can't be the loopback interface (lo). Sorry.");
+ return -EINVAL;
+ }
+
+ if (argc == 2)
+ return status_ifindex(bus, ifindex, NULL, STATUS_MDNS, NULL);
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkMulticastDNS",
+ &error,
+ NULL,
+ "is", ifindex, argv[2]);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
+ return log_interface_is_managed(r, ifindex);
+
+ if (arg_ifindex_permissive &&
+ sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
+ return 0;
+
+ return log_error_errno(r, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error, r));
+ }
+
+ return 0;
+}
+
+static int verb_dns_over_tls(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
+ int ifindex, r;
+
+ assert(bus);
+
+ if (argc <= 1)
+ return status_all(bus, STATUS_PRIVATE);
+
+ ifindex = parse_ifindex_with_warn(argv[1]);
+ if (ifindex < 0)
+ return ifindex;
+
+ if (ifindex == LOOPBACK_IFINDEX) {
+ log_error("Interface can't be the loopback interface (lo). Sorry.");
+ return -EINVAL;
+ }
+
+ if (argc == 2)
+ return status_ifindex(bus, ifindex, NULL, STATUS_PRIVATE, NULL);
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkDNSOverTLS",
+ &error,
+ NULL,
+ "is", ifindex, argv[2]);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
+ return log_interface_is_managed(r, ifindex);
+
+ if (arg_ifindex_permissive &&
+ sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
+ return 0;
+
+ return log_error_errno(r, "Failed to set DNSOverTLS configuration: %s", bus_error_message(&error, r));
+ }
+
+ return 0;
+}
+
+static int verb_dnssec(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
+ int ifindex, r;
+
+ assert(bus);
+
+ if (argc <= 1)
+ return status_all(bus, STATUS_DNSSEC);
+
+ ifindex = parse_ifindex_with_warn(argv[1]);
+ if (ifindex < 0)
+ return ifindex;
+
+ if (ifindex == LOOPBACK_IFINDEX) {
+ log_error("Interface can't be the loopback interface (lo). Sorry.");
+ return -EINVAL;
+ }
+
+ if (argc == 2)
+ return status_ifindex(bus, ifindex, NULL, STATUS_DNSSEC, NULL);
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkDNSSEC",
+ &error,
+ NULL,
+ "is", ifindex, argv[2]);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
+ return log_interface_is_managed(r, ifindex);
+
+ if (arg_ifindex_permissive &&
+ sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
+ return 0;
+
+ return log_error_errno(r, "Failed to set DNSSEC configuration: %s", bus_error_message(&error, r));
+ }
+
+ return 0;
+}
+
+static int verb_nta(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
+ sd_bus *bus = userdata;
+ int ifindex, i, r;
+
+ assert(bus);
+
+ if (argc <= 1)
+ return status_all(bus, STATUS_NTA);
+
+ ifindex = parse_ifindex_with_warn(argv[1]);
+ if (ifindex < 0)
+ return ifindex;
+
+ if (ifindex == LOOPBACK_IFINDEX) {
+ log_error("Interface can't be the loopback interface (lo). Sorry.");
+ return -EINVAL;
+ }
+
+ if (argc == 2)
+ return status_ifindex(bus, ifindex, NULL, STATUS_NTA, NULL);
+
+ for (i = 2; i < argc; i++) {
+ r = dns_name_is_valid(argv[i]);
+ if (r < 0)
+ return log_error_errno(r, "Failed to validate specified domain %s: %m", argv[i]);
+ if (r == 0) {
+ log_error("Domain not valid: %s", argv[i]);
+ return -EINVAL;
}
}
- return r;
+ r = sd_bus_message_new_method_call(
+ bus,
+ &req,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkDNSSECNegativeTrustAnchors");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(req, "i", ifindex);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_strv(req, argv + 2);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, req, 0, &error, NULL);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
+ return log_interface_is_managed(r, ifindex);
-is_managed:
- {
- char ifname[IFNAMSIZ];
+ if (arg_ifindex_permissive &&
+ sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
+ return 0;
- return log_error_errno(q,
- "The specified interface %s is managed by systemd-networkd. Operation refused.\n"
- "Please configure DNS settings for systemd-networkd managed interfaces directly in their .network files.", strna(if_indextoname(arg_ifindex, ifname)));
+ return log_error_errno(r, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error, r));
}
+
+ return 0;
}
-static int revert_link(sd_bus *bus) {
+static int verb_revert_link(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r;
+ sd_bus *bus = userdata;
+ int ifindex, r;
assert(bus);
+ ifindex = parse_ifindex_with_warn(argv[1]);
+ if (ifindex < 0)
+ return ifindex;
+
+ if (ifindex == LOOPBACK_IFINDEX) {
+ log_error("Interface can't be the loopback interface (lo). Sorry.");
+ return -EINVAL;
+ }
+
r = sd_bus_call_method(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
@@ -1776,9 +2280,14 @@ static int revert_link(sd_bus *bus) {
"RevertLink",
&error,
NULL,
- "i", arg_ifindex);
- if (r < 0)
+ "i", ifindex);
+ if (r < 0) {
+ if (arg_ifindex_permissive &&
+ sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
+ return 0;
+
return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r));
+ }
return 0;
}
@@ -1790,32 +2299,20 @@ static void help_protocol_types(void) {
}
static void help_dns_types(void) {
- const char *t;
- int i;
-
if (arg_legend)
puts("Known DNS RR types:");
- for (i = 0; i < _DNS_TYPE_MAX; i++) {
- t = dns_type_to_string(i);
- if (t)
- puts(t);
- }
+
+ DUMP_STRING_TABLE(dns_type, int, _DNS_TYPE_MAX);
}
static void help_dns_classes(void) {
- const char *t;
- int i;
-
if (arg_legend)
puts("Known DNS RR classes:");
- for (i = 0; i < _DNS_CLASS_MAX; i++) {
- t = dns_class_to_string(i);
- if (t)
- puts(t);
- }
+
+ DUMP_STRING_TABLE(dns_class, int, _DNS_CLASS_MAX);
}
-static void help(void) {
+static void compat_help(void) {
printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
"%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
"%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
@@ -1852,13 +2349,63 @@ static void help(void) {
" --set-domain=DOMAIN Set per-interface search domain\n"
" --set-llmnr=MODE Set per-interface LLMNR mode\n"
" --set-mdns=MODE Set per-interface MulticastDNS mode\n"
+ " --set-dnsovertls=MODE Set per-interface DNS-over-TLS mode\n"
" --set-dnssec=MODE Set per-interface DNSSEC mode\n"
" --set-nta=DOMAIN Set per-interface DNSSEC NTA\n"
" --revert Revert per-interface configuration\n"
, program_invocation_short_name);
}
-static int parse_argv(int argc, char *argv[]) {
+static void native_help(void) {
+ printf("%1$s [OPTIONS...] {COMMAND} ...\n"
+ "\n"
+ "Send control commands to the network name resolution manager, or\n"
+ "resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n"
+ "\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --no-pager Do not pipe output into a pager\n"
+ " -4 Resolve IPv4 addresses\n"
+ " -6 Resolve IPv6 addresses\n"
+ " -i --interface=INTERFACE Look on interface\n"
+ " -p --protocol=PROTO|help Look via protocol\n"
+ " -t --type=TYPE|help Query RR with DNS type\n"
+ " -c --class=CLASS|help Query RR with DNS class\n"
+ " --service-address=BOOL Resolve address for services (default: yes)\n"
+ " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
+ " --cname=BOOL Follow CNAME redirects (default: yes)\n"
+ " --search=BOOL Use search domains for single-label names\n"
+ " (default: yes)\n"
+ " --raw[=payload|packet] Dump the answer as binary data\n"
+ " --legend=BOOL Print headers and additional info (default: yes)\n"
+ "\n"
+ "Commands:\n"
+ " query HOSTNAME|ADDRESS... Resolve domain names, IPv4 and IPv6 addresses\n"
+ " service [[NAME] TYPE] DOMAIN Resolve service (SRV)\n"
+ " openpgp EMAIL@DOMAIN... Query OpenPGP public key\n"
+ " tlsa DOMAIN[:PORT]... Query TLS public key\n"
+ " status [LINK...] Show link and server status\n"
+ " statistics Show resolver statistics\n"
+ " reset-statistics Reset resolver statistics\n"
+ " flush-caches Flush all local DNS caches\n"
+ " reset-server-features Forget learnt DNS server feature levels\n"
+ " dns [LINK [SERVER...]] Get/set per-interface DNS server address\n"
+ " domain [LINK [DOMAIN...]] Get/set per-interface search domain\n"
+ " llmnr [LINK [MODE]] Get/set per-interface LLMNR mode\n"
+ " mdns [LINK [MODE]] Get/set per-interface MulticastDNS mode\n"
+ " dnsovertls [LINK [MODE]] Get/set per-interface DNS-over-TLS mode\n"
+ " dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode\n"
+ " nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA\n"
+ " revert LINK Revert per-interface configuration\n"
+ , program_invocation_short_name);
+}
+
+static int verb_help(int argc, char **argv, void *userdata) {
+ native_help();
+ return 0;
+}
+
+static int compat_parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_LEGEND,
@@ -1880,6 +2427,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SET_DOMAIN,
ARG_SET_LLMNR,
ARG_SET_MDNS,
+ ARG_SET_PRIVATE,
ARG_SET_DNSSEC,
ARG_SET_NTA,
ARG_REVERT_LINK,
@@ -1911,6 +2459,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "set-domain", required_argument, NULL, ARG_SET_DOMAIN },
{ "set-llmnr", required_argument, NULL, ARG_SET_LLMNR },
{ "set-mdns", required_argument, NULL, ARG_SET_MDNS },
+ { "set-dnsovertls", required_argument, NULL, ARG_SET_PRIVATE },
{ "set-dnssec", required_argument, NULL, ARG_SET_DNSSEC },
{ "set-nta", required_argument, NULL, ARG_SET_NTA },
{ "revert", no_argument, NULL, ARG_REVERT_LINK },
@@ -1926,7 +2475,7 @@ static int parse_argv(int argc, char *argv[]) {
switch(c) {
case 'h':
- help();
+ compat_help();
return 0; /* done */;
case ARG_VERSION:
@@ -1941,16 +2490,12 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'i':
- if (parse_ifindex(optarg, &arg_ifindex) < 0) {
- int ifi;
-
- ifi = if_nametoindex(optarg);
- if (ifi <= 0)
- return log_error_errno(errno, "Unknown interface %s: %m", optarg);
-
- arg_ifindex = ifi;
- }
+ r = parse_ifindex_with_warn(optarg);
+ if (r < 0)
+ return r;
+ arg_ifname = optarg;
+ arg_ifindex = r;
break;
case 't':
@@ -2029,8 +2574,9 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_TLSA:
arg_mode = MODE_RESOLVE_TLSA;
- arg_service_family = service_family_from_string(optarg);
- if (arg_service_family < 0) {
+ if (!optarg || service_family_is_valid(optarg))
+ arg_service_family = optarg;
+ else {
log_error("Unknown service family \"%s\".", optarg);
return -EINVAL;
}
@@ -2106,77 +2652,43 @@ static int parse_argv(int argc, char *argv[]) {
arg_no_pager = true;
break;
- case ARG_SET_DNS: {
- struct in_addr_data data, *n;
-
- r = in_addr_from_string_auto(optarg, &data.family, &data.address);
+ case ARG_SET_DNS:
+ r = strv_extend(&arg_set_dns, optarg);
if (r < 0)
- return log_error_errno(r, "Failed to parse DNS server address: %s", optarg);
-
- n = reallocarray(arg_set_dns, arg_n_set_dns + 1, sizeof(struct in_addr_data));
- if (!n)
return log_oom();
- arg_set_dns = n;
- arg_set_dns[arg_n_set_dns++] = data;
arg_mode = MODE_SET_LINK;
break;
- }
-
- case ARG_SET_DOMAIN: {
- const char *p;
-
- p = optarg[0] == '~' ? optarg + 1 : optarg;
-
- r = dns_name_is_valid(p);
- if (r < 0)
- return log_error_errno(r, "Failed to validate specified domain %s: %m", p);
- if (r == 0) {
- log_error("Domain not valid: %s", p);
- return -EINVAL;
- }
+ case ARG_SET_DOMAIN:
r = strv_extend(&arg_set_domain, optarg);
if (r < 0)
return log_oom();
arg_mode = MODE_SET_LINK;
break;
- }
case ARG_SET_LLMNR:
- r = free_and_strdup(&arg_set_llmnr, optarg);
- if (r < 0)
- return log_oom();
-
+ arg_set_llmnr = optarg;
arg_mode = MODE_SET_LINK;
break;
case ARG_SET_MDNS:
- r = free_and_strdup(&arg_set_mdns, optarg);
- if (r < 0)
- return log_oom();
+ arg_set_mdns = optarg;
+ arg_mode = MODE_SET_LINK;
+ break;
+ case ARG_SET_PRIVATE:
+ arg_set_dns_over_tls = optarg;
arg_mode = MODE_SET_LINK;
break;
case ARG_SET_DNSSEC:
- r = free_and_strdup(&arg_set_dnssec, optarg);
- if (r < 0)
- return log_oom();
-
+ arg_set_dnssec = optarg;
arg_mode = MODE_SET_LINK;
break;
case ARG_SET_NTA:
- r = dns_name_is_valid(optarg);
- if (r < 0)
- return log_error_errno(r, "Failed to validate specified domain %s: %m", optarg);
- if (r == 0) {
- log_error("Domain not valid: %s", optarg);
- return -EINVAL;
- }
-
r = strv_extend(&arg_set_nta, optarg);
if (r < 0)
return log_oom();
@@ -2214,7 +2726,7 @@ static int parse_argv(int argc, char *argv[]) {
if (IN_SET(arg_mode, MODE_SET_LINK, MODE_REVERT_LINK)) {
if (arg_ifindex <= 0) {
- log_error("--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnssec=, --set-nta= and --revert require --interface=.");
+ log_error("--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnsovertls=, --set-dnssec=, --set-nta= and --revert require --interface=.");
return -EINVAL;
}
@@ -2227,225 +2739,373 @@ static int parse_argv(int argc, char *argv[]) {
return 1 /* work to do */;
}
-int main(int argc, char **argv) {
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- int r;
+static int native_parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_LEGEND,
+ ARG_CNAME,
+ ARG_SERVICE_ADDRESS,
+ ARG_SERVICE_TXT,
+ ARG_RAW,
+ ARG_SEARCH,
+ ARG_NO_PAGER,
+ };
- log_parse_environment();
- log_open();
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "type", required_argument, NULL, 't' },
+ { "class", required_argument, NULL, 'c' },
+ { "legend", required_argument, NULL, ARG_LEGEND },
+ { "interface", required_argument, NULL, 'i' },
+ { "protocol", required_argument, NULL, 'p' },
+ { "cname", required_argument, NULL, ARG_CNAME },
+ { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
+ { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
+ { "raw", optional_argument, NULL, ARG_RAW },
+ { "search", required_argument, NULL, ARG_SEARCH },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ {}
+ };
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
+ int c, r;
- r = sd_bus_open_system(&bus);
- if (r < 0) {
- log_error_errno(r, "sd_bus_open_system: %m");
- goto finish;
- }
+ assert(argc >= 0);
+ assert(argv);
- switch (arg_mode) {
+ while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
+ switch(c) {
- case MODE_RESOLVE_HOST:
- if (optind >= argc) {
- log_error("No arguments passed.");
- r = -EINVAL;
- goto finish;
- }
+ case 'h':
+ native_help();
+ return 0; /* done */;
+
+ case ARG_VERSION:
+ return version();
+
+ case '4':
+ arg_family = AF_INET;
+ break;
+
+ case '6':
+ arg_family = AF_INET6;
+ break;
+
+ case 'i':
+ r = parse_ifindex_with_warn(optarg);
+ if (r < 0)
+ return r;
+
+ arg_ifindex = r;
+ break;
+
+ case 't':
+ if (streq(optarg, "help")) {
+ help_dns_types();
+ return 0;
+ }
+
+ r = dns_type_from_string(optarg);
+ if (r < 0) {
+ log_error("Failed to parse RR record type %s", optarg);
+ return r;
+ }
+ arg_type = (uint16_t) r;
+ assert((int) arg_type == r);
+
+ break;
+
+ case 'c':
+ if (streq(optarg, "help")) {
+ help_dns_classes();
+ return 0;
+ }
+
+ r = dns_class_from_string(optarg);
+ if (r < 0) {
+ log_error("Failed to parse RR record class %s", optarg);
+ return r;
+ }
+ arg_class = (uint16_t) r;
+ assert((int) arg_class == r);
+
+ break;
- while (argv[optind]) {
- int family, ifindex, k;
- union in_addr_union a;
+ case ARG_LEGEND:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --legend= argument");
+
+ arg_legend = r;
+ break;
- if (startswith(argv[optind], "dns:"))
- k = resolve_rfc4501(bus, argv[optind]);
+ case 'p':
+ if (streq(optarg, "help")) {
+ help_protocol_types();
+ return 0;
+ } else if (streq(optarg, "dns"))
+ arg_flags |= SD_RESOLVED_DNS;
+ else if (streq(optarg, "llmnr"))
+ arg_flags |= SD_RESOLVED_LLMNR;
+ else if (streq(optarg, "llmnr-ipv4"))
+ arg_flags |= SD_RESOLVED_LLMNR_IPV4;
+ else if (streq(optarg, "llmnr-ipv6"))
+ arg_flags |= SD_RESOLVED_LLMNR_IPV6;
+ else if (streq(optarg, "mdns"))
+ arg_flags |= SD_RESOLVED_MDNS;
+ else if (streq(optarg, "mdns-ipv4"))
+ arg_flags |= SD_RESOLVED_MDNS_IPV4;
+ else if (streq(optarg, "mdns-ipv6"))
+ arg_flags |= SD_RESOLVED_MDNS_IPV6;
else {
- k = in_addr_ifindex_from_string_auto(argv[optind], &family, &a, &ifindex);
- if (k >= 0)
- k = resolve_address(bus, family, &a, ifindex);
- else
- k = resolve_host(bus, argv[optind]);
+ log_error("Unknown protocol specifier: %s", optarg);
+ return -EINVAL;
}
- if (r == 0)
- r = k;
+ break;
- optind++;
- }
- break;
+ case ARG_RAW:
+ if (on_tty()) {
+ log_error("Refusing to write binary data to tty.");
+ return -ENOTTY;
+ }
- case MODE_RESOLVE_RECORD:
- if (optind >= argc) {
- log_error("No arguments passed.");
- r = -EINVAL;
- goto finish;
- }
+ if (optarg == NULL || streq(optarg, "payload"))
+ arg_raw = RAW_PAYLOAD;
+ else if (streq(optarg, "packet"))
+ arg_raw = RAW_PACKET;
+ else {
+ log_error("Unknown --raw specifier \"%s\".", optarg);
+ return -EINVAL;
+ }
- while (argv[optind]) {
- int k;
+ arg_legend = false;
+ break;
- k = resolve_record(bus, argv[optind], arg_class, arg_type, true);
- if (r == 0)
- r = k;
+ case ARG_CNAME:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --cname= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
+ break;
- optind++;
- }
- break;
+ case ARG_SERVICE_ADDRESS:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --service-address= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
+ break;
- case MODE_RESOLVE_SERVICE:
- if (argc < optind + 1) {
- log_error("Domain specification required.");
- r = -EINVAL;
- goto finish;
-
- } else if (argc == optind + 1)
- r = resolve_service(bus, NULL, NULL, argv[optind]);
- else if (argc == optind + 2)
- r = resolve_service(bus, NULL, argv[optind], argv[optind+1]);
- else if (argc == optind + 3)
- r = resolve_service(bus, argv[optind], argv[optind+1], argv[optind+2]);
- else {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
- }
+ case ARG_SERVICE_TXT:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --service-txt= argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
+ break;
- break;
+ case ARG_SEARCH:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --search argument.");
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
+ break;
- case MODE_RESOLVE_OPENPGP:
- if (argc < optind + 1) {
- log_error("E-mail address required.");
- r = -EINVAL;
- goto finish;
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached("Unhandled option");
}
- r = 0;
- while (optind < argc) {
- int k;
+ if (arg_type == 0 && arg_class != 0) {
+ log_error("--class= may only be used in conjunction with --type=.");
+ return -EINVAL;
+ }
- k = resolve_openpgp(bus, argv[optind++]);
- if (k < 0)
- r = k;
- }
- break;
+ if (arg_type != 0 && arg_class == 0)
+ arg_class = DNS_CLASS_IN;
- case MODE_RESOLVE_TLSA:
- if (argc < optind + 1) {
- log_error("Domain name required.");
- r = -EINVAL;
- goto finish;
+ if (arg_class != 0 && arg_type == 0)
+ arg_type = DNS_TYPE_A;
- }
+ return 1 /* work to do */;
+}
- r = 0;
- while (optind < argc) {
- int k;
+static int native_main(int argc, char *argv[], sd_bus *bus) {
+
+ static const Verb verbs[] = {
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help },
+ { "status", VERB_ANY, VERB_ANY, VERB_DEFAULT, verb_status },
+ { "query", 2, VERB_ANY, 0, verb_query },
+ { "service", 2, 4, 0, verb_service },
+ { "openpgp", 2, VERB_ANY, 0, verb_openpgp },
+ { "tlsa", 2, VERB_ANY, 0, verb_tlsa },
+ { "statistics", VERB_ANY, 1, 0, show_statistics },
+ { "reset-statistics", VERB_ANY, 1, 0, reset_statistics },
+ { "flush-caches", VERB_ANY, 1, 0, flush_caches },
+ { "reset-server-features", VERB_ANY, 1, 0, reset_server_features },
+ { "dns", VERB_ANY, VERB_ANY, 0, verb_dns },
+ { "domain", VERB_ANY, VERB_ANY, 0, verb_domain },
+ { "llmnr", VERB_ANY, 3, 0, verb_llmnr },
+ { "mdns", VERB_ANY, 3, 0, verb_mdns },
+ { "dnsovertls", VERB_ANY, 3, 0, verb_dns_over_tls },
+ { "dnssec", VERB_ANY, 3, 0, verb_dnssec },
+ { "nta", VERB_ANY, VERB_ANY, 0, verb_nta },
+ { "revert", 2, 2, 0, verb_revert_link },
+ {}
+ };
- k = resolve_tlsa(bus, argv[optind++]);
- if (k < 0)
- r = k;
- }
- break;
+ return dispatch_verb(argc, argv, verbs, bus);
+}
- case MODE_STATISTICS:
- if (argc > optind) {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
- }
+static int translate(const char *verb, const char *single_arg, size_t num_args, char **args, sd_bus *bus) {
+ char **fake, **p;
+ size_t num, i;
- r = show_statistics(bus);
- break;
+ assert(verb);
+ assert(num_args == 0 || args);
- case MODE_RESET_STATISTICS:
- if (argc > optind) {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
- }
+ num = !!single_arg + num_args + 1;
- r = reset_statistics(bus);
- break;
+ p = fake = newa0(char *, num + 1);
+ *p++ = (char *) verb;
+ if (single_arg)
+ *p++ = (char *) single_arg;
+ for (i = 0; i < num_args; i++)
+ *p++ = args[i];
- case MODE_FLUSH_CACHES:
- if (argc > optind) {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
- }
+ optind = 0;
+ return native_main((int) num, fake, bus);
+}
+
+static int compat_main(int argc, char *argv[], sd_bus *bus) {
+ int r = 0;
- r = flush_caches(bus);
- break;
+ switch (arg_mode) {
+ case MODE_RESOLVE_HOST:
+ case MODE_RESOLVE_RECORD:
+ return translate("query", NULL, argc - optind, argv + optind, bus);
+
+ case MODE_RESOLVE_SERVICE:
+ return translate("service", NULL, argc - optind, argv + optind, bus);
+
+ case MODE_RESOLVE_OPENPGP:
+ return translate("openpgp", NULL, argc - optind, argv + optind, bus);
+
+ case MODE_RESOLVE_TLSA:
+ return translate("tlsa", arg_service_family, argc - optind, argv + optind, bus);
+
+ case MODE_STATISTICS:
+ return translate("statistics", NULL, 0, NULL, bus);
+
+ case MODE_RESET_STATISTICS:
+ return translate("reset-statistics", NULL, 0, NULL, bus);
+
+ case MODE_FLUSH_CACHES:
+ return translate("flush-caches", NULL, 0, NULL, bus);
case MODE_RESET_SERVER_FEATURES:
- if (argc > optind) {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
+ return translate("reset-server-features", NULL, 0, NULL, bus);
+
+ case MODE_STATUS:
+ return translate("status", NULL, argc - optind, argv + optind, bus);
+
+ case MODE_SET_LINK:
+ if (arg_set_dns) {
+ r = translate("dns", arg_ifname, strv_length(arg_set_dns), arg_set_dns, bus);
+ if (r < 0)
+ return r;
}
- r = reset_server_features(bus);
- break;
+ if (arg_set_domain) {
+ r = translate("domain", arg_ifname, strv_length(arg_set_domain), arg_set_domain, bus);
+ if (r < 0)
+ return r;
+ }
- case MODE_STATUS:
+ if (arg_set_nta) {
+ r = translate("nta", arg_ifname, strv_length(arg_set_nta), arg_set_nta, bus);
+ if (r < 0)
+ return r;
+ }
- if (argc > optind) {
- char **ifname;
- bool empty_line = false;
-
- r = 0;
- STRV_FOREACH(ifname, argv + optind) {
- int ifindex, q;
-
- q = parse_ifindex(*ifname, &ifindex);
- if (q < 0) {
- ifindex = if_nametoindex(*ifname);
- if (ifindex <= 0) {
- log_error_errno(errno, "Failed to resolve interface name '%s': %m", *ifname);
- continue;
- }
- }
+ if (arg_set_llmnr) {
+ r = translate("llmnr", arg_ifname, 1, (char **) &arg_set_llmnr, bus);
+ if (r < 0)
+ return r;
+ }
- q = status_ifindex(bus, ifindex, NULL, &empty_line);
- if (q < 0 && r >= 0)
- r = q;
- }
- } else
- r = status_all(bus);
+ if (arg_set_mdns) {
+ r = translate("mdns", arg_ifname, 1, (char **) &arg_set_mdns, bus);
+ if (r < 0)
+ return r;
+ }
- break;
+ if (arg_set_dns_over_tls) {
+ r = translate("dnsovertls", arg_ifname, 1, (char **) &arg_set_dns_over_tls, bus);
+ if (r < 0)
+ return r;
+ }
- case MODE_SET_LINK:
- if (argc > optind) {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
+ if (arg_set_dnssec) {
+ r = translate("dnssec", arg_ifname, 1, (char **) &arg_set_dnssec, bus);
+ if (r < 0)
+ return r;
}
- r = set_link(bus);
- break;
+ return r;
case MODE_REVERT_LINK:
- if (argc > optind) {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
- }
+ return translate("revert", arg_ifname, 0, NULL, bus);
- r = revert_link(bus);
- break;
+ case _MODE_INVALID:
+ assert_not_reached("invalid mode");
}
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ sd_bus *bus = NULL;
+ int r;
+
+ setlocale(LC_ALL, "");
+ log_parse_environment();
+ log_open();
+
+ if (streq(program_invocation_short_name, "resolvconf"))
+ r = resolvconf_parse_argv(argc, argv);
+ else if (streq(program_invocation_short_name, "systemd-resolve"))
+ r = compat_parse_argv(argc, argv);
+ else
+ r = native_parse_argv(argc, argv);
+ if (r <= 0)
+ goto finish;
+
+ r = sd_bus_open_system(&bus);
+ if (r < 0) {
+ log_error_errno(r, "sd_bus_open_system: %m");
+ goto finish;
+ }
+
+ if (streq(program_invocation_short_name, "systemd-resolve"))
+ r = compat_main(argc, argv, bus);
+ else
+ r = native_main(argc, argv, bus);
+
finish:
+ /* make sure we terminate the bus connection first, and then close the
+ * pager, see issue #3543 for the details. */
+ sd_bus_flush_close_unref(bus);
pager_close();
- free(arg_set_dns);
+ strv_free(arg_set_dns);
strv_free(arg_set_domain);
- free(arg_set_llmnr);
- free(arg_set_mdns);
- free(arg_set_dnssec);
strv_free(arg_set_nta);
- return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/resolve/resolvectl.h b/src/resolve/resolvectl.h
new file mode 100644
index 0000000000..6ecaa4ff31
--- /dev/null
+++ b/src/resolve/resolvectl.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <in-addr-util.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+extern int arg_ifindex;
+extern const char *arg_ifname;
+extern bool arg_ifindex_permissive;
+
+typedef enum ExecutionMode {
+ MODE_RESOLVE_HOST,
+ MODE_RESOLVE_RECORD,
+ MODE_RESOLVE_SERVICE,
+ MODE_RESOLVE_OPENPGP,
+ MODE_RESOLVE_TLSA,
+ MODE_STATISTICS,
+ MODE_RESET_STATISTICS,
+ MODE_FLUSH_CACHES,
+ MODE_RESET_SERVER_FEATURES,
+ MODE_STATUS,
+ MODE_SET_LINK,
+ MODE_REVERT_LINK,
+ _MODE_INVALID = -1,
+} ExecutionMode;
+
+extern ExecutionMode arg_mode;
+
+extern char **arg_set_dns;
+extern char **arg_set_domain;
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index ffd7c4824e..da0a909dd6 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-common-errors.h"
@@ -31,6 +13,8 @@
#include "user-util.h"
#include "utf8.h"
+BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support, resolve_support, ResolveSupport);
+
static int reply_query_state(DnsQuery *q) {
switch (q->state) {
@@ -1230,7 +1214,13 @@ int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex
int r;
assert(reply);
- assert(s);
+
+ if (!s) {
+ if (with_ifindex)
+ return sd_bus_message_append(reply, "(iiay)", 0, AF_UNSPEC, 0);
+ else
+ return sd_bus_message_append(reply, "(iay)", AF_UNSPEC, 0);
+ }
r = sd_bus_message_open_container(reply, 'r', with_ifindex ? "iiay" : "iay");
if (r < 0)
@@ -1263,7 +1253,6 @@ static int bus_property_get_dns_servers(
sd_bus_error *error) {
Manager *m = userdata;
- unsigned c = 0;
DnsServer *s;
Iterator i;
Link *l;
@@ -1280,8 +1269,6 @@ static int bus_property_get_dns_servers(
r = bus_dns_server_append(reply, s, true);
if (r < 0)
return r;
-
- c++;
}
HASHMAP_FOREACH(l, m->links, i) {
@@ -1289,21 +1276,59 @@ static int bus_property_get_dns_servers(
r = bus_dns_server_append(reply, s, true);
if (r < 0)
return r;
- c++;
}
}
- if (c == 0) {
- LIST_FOREACH(servers, s, m->fallback_dns_servers) {
- r = bus_dns_server_append(reply, s, true);
- if (r < 0)
- return r;
- }
+ return sd_bus_message_close_container(reply);
+}
+
+static int bus_property_get_fallback_dns_servers(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ DnsServer *s, **f = userdata;
+ int r;
+
+ assert(reply);
+ assert(f);
+
+ r = sd_bus_message_open_container(reply, 'a', "(iiay)");
+ if (r < 0)
+ return r;
+
+ LIST_FOREACH(servers, s, *f) {
+ r = bus_dns_server_append(reply, s, true);
+ if (r < 0)
+ return r;
}
return sd_bus_message_close_container(reply);
}
+static int bus_property_get_current_dns_server(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ DnsServer *s;
+
+ assert(reply);
+ assert(userdata);
+
+ s = *(DnsServer **) userdata;
+
+ return bus_dns_server_append(reply, s, true);
+}
+
static int bus_property_get_domains(
sd_bus *bus,
const char *path,
@@ -1408,23 +1433,6 @@ static int bus_property_get_dnssec_statistics(
(uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]);
}
-static int bus_property_get_dnssec_supported(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "b", manager_dnssec_supported(m));
-}
-
static int bus_property_get_ntas(
sd_bus *bus,
const char *path,
@@ -1456,6 +1464,9 @@ static int bus_property_get_ntas(
}
static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode);
+static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported, "b", Manager, manager_dnssec_supported);
+static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string);
+static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dns_over_tls_mode, "s", Manager, manager_get_dns_over_tls_mode, dns_over_tls_mode_to_string);
static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
@@ -1526,6 +1537,10 @@ static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_
return call_link_method(userdata, message, bus_link_method_set_mdns, error);
}
+static int bus_method_set_link_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return call_link_method(userdata, message, bus_link_method_set_dns_over_tls, error);
+}
+
static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
}
@@ -1814,10 +1829,16 @@ static int bus_method_unregister_service(sd_bus_message *message, void *userdata
static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
+ SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Manager, llmnr_support), 0),
+ SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Manager, mdns_support), 0),
+ SD_BUS_PROPERTY("DNSOverTLS", "s", bus_property_get_dns_over_tls_mode, 0, 0),
SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0),
+ SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server, offsetof(Manager, current_dns_server), 0),
SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0),
SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
+ SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode, 0, 0),
SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0),
@@ -1835,6 +1856,7 @@ static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, 0),
SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0),
SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0),
+ SD_BUS_METHOD("SetLinkDNSOverTLS", "is", NULL, bus_method_set_link_dns_over_tls, 0),
SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0),
SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, 0),
SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, 0),
@@ -1874,7 +1896,7 @@ int manager_connect_bus(Manager *m) {
if (m->bus)
return 0;
- r = bus_open_system_watch_bind(&m->bus);
+ r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-resolve");
if (r < 0)
return log_error_errno(r, "Failed to connect to system bus: %m");
@@ -1898,7 +1920,7 @@ int manager_connect_bus(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to register dnssd enumerator: %m");
- r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL);
+ r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL);
if (r < 0)
return log_error_errno(r, "Failed to request name: %m");
diff --git a/src/resolve/resolved-bus.h b/src/resolve/resolved-bus.h
index 11ddae9d8d..a52bb0fa69 100644
--- a/src/resolve/resolved-bus.h
+++ b/src/resolve/resolved-bus.h
@@ -1,26 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "resolved-manager.h"
int manager_connect_bus(Manager *m);
int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex);
+int bus_property_get_resolve_support(sd_bus *bus, const char *path, const char *interface,
+ const char *property, sd_bus_message *reply,
+ void *userdata, sd_bus_error *error);
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index ca69d70e3c..79e388f8a2 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
#include "alloc-util.h"
#include "conf-parser.h"
@@ -235,8 +217,8 @@ int config_parse_search_domains(
int config_parse_dnssd_service_name(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) {
static const Specifier specifier_table[] = {
{ 'b', specifier_boot_id, NULL },
- { 'H', specifier_host_name, NULL },
- { 'm', specifier_machine_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'm', specifier_machine_id, NULL },
{ 'v', specifier_kernel_release, NULL },
{}
};
@@ -337,10 +319,8 @@ int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line
r = split_pair(word, "=", &key, &value);
if (r == -ENOMEM)
return log_oom();
- if (r == -EINVAL) {
- key = word;
- word = NULL;
- }
+ if (r == -EINVAL)
+ key = TAKE_PTR(word);
if (!ascii_is_valid(key)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring: %s", key);
@@ -411,6 +391,13 @@ int manager_parse_config_file(Manager *m) {
m->dnssec_mode = DNSSEC_NO;
}
#endif
+
+#if ! ENABLE_DNS_OVER_TLS
+ if (m->dns_over_tls_mode != DNS_OVER_TLS_NO) {
+ log_warning("DNS-over-TLS option cannot be set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
+ m->dns_over_tls_mode = DNS_OVER_TLS_NO;
+ }
+#endif
return 0;
}
diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h
index 4ebb45f3aa..0a0a110534 100644
--- a/src/resolve/resolved-conf.h
+++ b/src/resolve/resolved-conf.h
@@ -1,24 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "conf-parser.h"
typedef enum DnsStubListenerMode DnsStubListenerMode;
@@ -43,15 +27,14 @@ int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char
int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string);
const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-
const struct ConfigPerfItem* resolved_dnssd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-int config_parse_dns_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dns_stub_listener_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssd_service_name(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssd_service_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns_servers);
+CONFIG_PARSER_PROTOTYPE(config_parse_search_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt);
const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_;
DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_;
diff --git a/src/resolve/resolved-def.h b/src/resolve/resolved-def.h
index 96f93107ad..ea2851b7b1 100644
--- a/src/resolve/resolved-def.h
+++ b/src/resolve/resolved-def.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <inttypes.h>
#include "time-util.h"
@@ -41,3 +22,6 @@
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
#define SD_RESOLVED_QUERY_TIMEOUT_USEC (120 * USEC_PER_SEC)
+
+/* 127.0.0.53 in native endian */
+#define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U)
diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c
index ecc6143e62..26caa63f94 100644
--- a/src/resolve/resolved-dns-answer.c
+++ b/src/resolve/resolved-dns-answer.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "dns-domain.h"
@@ -24,7 +6,7 @@
#include "resolved-dns-dnssec.h"
#include "string-util.h"
-DnsAnswer *dns_answer_new(unsigned n) {
+DnsAnswer *dns_answer_new(size_t n) {
DnsAnswer *a;
a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n);
@@ -106,7 +88,7 @@ static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
}
int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
- unsigned i;
+ size_t i;
int r;
assert(rr);
@@ -442,8 +424,7 @@ int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) {
if (r < 0)
return r;
- *ret = k;
- k = NULL;
+ *ret = TAKE_PTR(k);
return 0;
}
@@ -467,7 +448,7 @@ int dns_answer_extend(DnsAnswer **a, DnsAnswer *b) {
int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
bool found = false, other = false;
DnsResourceRecord *rr;
- unsigned i;
+ size_t i;
int r;
assert(a);
@@ -518,8 +499,7 @@ int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
}
dns_answer_unref(*a);
- *a = copy;
- copy = NULL;
+ *a = TAKE_PTR(copy);
return 1;
}
@@ -553,7 +533,7 @@ int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
bool found = false, other = false;
DnsResourceRecord *rr;
- unsigned i;
+ size_t i;
int r;
assert(a);
@@ -604,8 +584,7 @@ int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
}
dns_answer_unref(*a);
- *a = copy;
- copy = NULL;
+ *a = TAKE_PTR(copy);
return 1;
}
@@ -683,7 +662,7 @@ int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKe
void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
DnsAnswerItem *items;
- unsigned i, start, end;
+ size_t i, start, end;
if (!a)
return;
@@ -714,7 +693,7 @@ void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
memcpy(a->items, items, sizeof(DnsAnswerItem) * a->n_rrs);
}
-int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
+int dns_answer_reserve(DnsAnswer **a, size_t n_free) {
DnsAnswer *n;
assert(a);
@@ -723,7 +702,7 @@ int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
return 0;
if (*a) {
- unsigned ns;
+ size_t ns;
if ((*a)->n_ref > 1)
return -EBUSY;
@@ -751,7 +730,7 @@ int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
return 0;
}
-int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free) {
+int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) {
_cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
int r;
@@ -778,8 +757,7 @@ int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free) {
return r;
dns_answer_unref(*a);
- *a = n;
- n = NULL;
+ *a = TAKE_PTR(n);
return 0;
}
diff --git a/src/resolve/resolved-dns-answer.h b/src/resolve/resolved-dns-answer.h
index af33787044..aff594a00e 100644
--- a/src/resolve/resolved-dns-answer.h
+++ b/src/resolve/resolved-dns-answer.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct DnsAnswer DnsAnswer;
typedef struct DnsAnswerItem DnsAnswerItem;
@@ -49,11 +30,11 @@ struct DnsAnswerItem {
struct DnsAnswer {
unsigned n_ref;
- unsigned n_rrs, n_allocated;
+ size_t n_rrs, n_allocated;
DnsAnswerItem items[0];
};
-DnsAnswer *dns_answer_new(unsigned n);
+DnsAnswer *dns_answer_new(size_t n);
DnsAnswer *dns_answer_ref(DnsAnswer *a);
DnsAnswer *dns_answer_unref(DnsAnswer *a);
@@ -75,8 +56,8 @@ int dns_answer_extend(DnsAnswer **a, DnsAnswer *b);
void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local);
-int dns_answer_reserve(DnsAnswer **a, unsigned n_free);
-int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free);
+int dns_answer_reserve(DnsAnswer **a, size_t n_free);
+int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free);
int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key);
int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr);
@@ -86,7 +67,7 @@ int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKe
bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname);
-static inline unsigned dns_answer_size(DnsAnswer *a) {
+static inline size_t dns_answer_size(DnsAnswer *a) {
return a ? a->n_rrs : 0;
}
@@ -99,7 +80,7 @@ void dns_answer_dump(DnsAnswer *answer, FILE *f);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
#define _DNS_ANSWER_FOREACH(q, kk, a) \
- for (unsigned UNIQ_T(i, q) = ({ \
+ for (size_t UNIQ_T(i, q) = ({ \
(kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
0; \
}); \
@@ -109,7 +90,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
#define DNS_ANSWER_FOREACH(kk, a) _DNS_ANSWER_FOREACH(UNIQ, kk, a)
#define _DNS_ANSWER_FOREACH_IFINDEX(q, kk, ifi, a) \
- for (unsigned UNIQ_T(i, q) = ({ \
+ for (size_t UNIQ_T(i, q) = ({ \
(kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
(ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
0; \
@@ -122,7 +103,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
#define DNS_ANSWER_FOREACH_IFINDEX(kk, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(UNIQ, kk, ifindex, a)
#define _DNS_ANSWER_FOREACH_FLAGS(q, kk, fl, a) \
- for (unsigned UNIQ_T(i, q) = ({ \
+ for (size_t UNIQ_T(i, q) = ({ \
(kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
(fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
0; \
@@ -135,7 +116,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
#define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a)
#define _DNS_ANSWER_FOREACH_FULL(q, kk, ifi, fl, a) \
- for (unsigned UNIQ_T(i, q) = ({ \
+ for (size_t UNIQ_T(i, q) = ({ \
(kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
(ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
(fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index e9197f1dfd..23cd662fb8 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
@@ -667,12 +649,13 @@ int dns_cache_put(
* short time.) */
if (IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN)) {
-
if (dns_answer_size(answer) <= 0) {
- char key_str[DNS_RESOURCE_KEY_STRING_MAX];
+ if (key) {
+ char key_str[DNS_RESOURCE_KEY_STRING_MAX];
- log_debug("Not caching negative entry without a SOA record: %s",
- dns_resource_key_to_string(key, key_str, sizeof key_str));
+ log_debug("Not caching negative entry without a SOA record: %s",
+ dns_resource_key_to_string(key, key_str, sizeof key_str));
+ }
return 0;
}
diff --git a/src/resolve/resolved-dns-cache.h b/src/resolve/resolved-dns-cache.h
index a5ace2c4c6..48a3bde98b 100644
--- a/src/resolve/resolved-dns-cache.h
+++ b/src/resolve/resolved-dns-cache.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "hashmap.h"
#include "list.h"
#include "prioq.h"
diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c
index 1bd2c93a33..0a6f482cc1 100644
--- a/src/resolve/resolved-dns-dnssec.c
+++ b/src/resolve/resolved-dns-dnssec.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio_ext.h>
@@ -713,7 +695,7 @@ int dnssec_verify_rrset(
usec_t realtime,
DnssecResult *result) {
- uint8_t wire_format_name[DNS_WIRE_FOMAT_HOSTNAME_MAX];
+ uint8_t wire_format_name[DNS_WIRE_FORMAT_HOSTNAME_MAX];
DnsResourceRecord **list, *rr;
const char *source, *name;
_cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
@@ -1166,7 +1148,7 @@ static int digest_to_gcrypt_md(uint8_t algorithm) {
}
int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
- char owner_name[DNSSEC_CANONICAL_HOSTNAME_MAX];
+ uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
_cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
size_t hash_size;
int md_algorithm, r;
@@ -1205,7 +1187,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
if (ds->ds.digest_size != hash_size)
return 0;
- r = dnssec_canonicalize(dns_resource_key_name(dnskey->key), owner_name, sizeof(owner_name));
+ r = dns_name_to_wire_format(dns_resource_key_name(dnskey->key), wire_format, sizeof(wire_format), true);
if (r < 0)
return r;
@@ -1213,7 +1195,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
if (!md)
return -EIO;
- gcry_md_write(md, owner_name, r);
+ gcry_md_write(md, wire_format, r);
if (mask_revoke)
md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
else
@@ -1226,7 +1208,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
if (!result)
return -EIO;
- return memcmp(result, ds->ds.digest, ds->ds.digest_size) != 0;
+ return memcmp(result, ds->ds.digest, ds->ds.digest_size) == 0;
}
int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
@@ -1282,7 +1264,7 @@ static int nsec3_hash_to_gcrypt_md(uint8_t algorithm) {
}
int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
- uint8_t wire_format[DNS_WIRE_FOMAT_HOSTNAME_MAX];
+ uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
gcry_md_hd_t md = NULL;
size_t hash_size;
int algorithm;
@@ -1806,41 +1788,29 @@ static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name)
}
static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) {
- const char *common_suffix, *p;
+ const char *signer;
int r;
assert(rr);
assert(rr->key->type == DNS_TYPE_NSEC);
- /* Checks whether the "Next Closer" is witin the space covered by the specified RR. */
+ /* Checks whether the name is covered by this NSEC RR. This means, that the name is somewhere below the NSEC's
+ * signer name, and between the NSEC's two names. */
- r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
+ r = dns_resource_record_signer(rr, &signer);
if (r < 0)
return r;
- for (;;) {
- p = name;
- r = dns_name_parent(&name);
- if (r < 0)
- return r;
- if (r == 0)
- return 0;
-
- r = dns_name_equal(name, common_suffix);
- if (r < 0)
- return r;
- if (r > 0)
- break;
- }
-
- /* p is now the "Next Closer". */
+ r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */
+ if (r <= 0)
+ return r;
- return dns_name_between(dns_resource_key_name(rr->key), p, rr->nsec.next_domain_name);
+ return dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
}
static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name) {
_cleanup_free_ char *wc = NULL;
- const char *common_suffix;
+ const char *common_suffix, *signer;
int r;
assert(rr);
@@ -1855,16 +1825,27 @@ static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name)
* NSEC yyy.zzz.xoo.bar → bar: indicates that a number of wildcards don#t exist either...
*/
- r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
+ r = dns_resource_record_signer(rr, &signer);
if (r < 0)
return r;
- /* If the common suffix is not shared by the name we are interested in, it has nothing to say for us. */
- r = dns_name_endswith(name, common_suffix);
+ r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */
if (r <= 0)
return r;
- r = dns_name_concat("*", common_suffix, &wc);
+ r = dns_name_endswith(name, dns_resource_key_name(rr->key));
+ if (r < 0)
+ return r;
+ if (r > 0) /* If the name we are interested in is a child of the NSEC RR, then append the asterisk to the NSEC
+ * RR's name. */
+ r = dns_name_concat("*", dns_resource_key_name(rr->key), &wc);
+ else {
+ r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
+ if (r < 0)
+ return r;
+
+ r = dns_name_concat("*", common_suffix, &wc);
+ }
if (r < 0)
return r;
diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h
index 25e3e08c1b..dfee7232c0 100644
--- a/src/resolve/resolved-dns-dnssec.h
+++ b/src/resolve/resolved-dns-dnssec.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef enum DnssecResult DnssecResult;
typedef enum DnssecVerdict DnssecVerdict;
@@ -93,7 +74,6 @@ typedef enum DnssecNsecResult {
int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl);
-
int dnssec_test_positive_wildcard(DnsAnswer *a, const char *name, const char *source, const char *zone, bool *authenticated);
const char* dnssec_result_to_string(DnssecResult m) _const_;
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 2067dd5182..5266014581 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#if HAVE_GCRYPT
@@ -1472,8 +1456,7 @@ int dns_packet_read_name(
if (after_rindex != 0)
p->rindex= after_rindex;
- *_ret = ret;
- ret = NULL;
+ *_ret = TAKE_PTR(ret);
if (start)
*start = rewinder.saved_rindex;
@@ -2084,8 +2067,7 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_fl
if (p->rindex != offset + rdlength)
return -EBADMSG;
- *ret = rr;
- rr = NULL;
+ *ret = TAKE_PTR(rr);
if (ret_cache_flush)
*ret_cache_flush = cache_flush;
@@ -2171,8 +2153,8 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
}
}
- *ret_question = question;
- question = NULL;
+ *ret_question = TAKE_PTR(question);
+
return 0;
}
@@ -2287,8 +2269,8 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
if (bad_opt)
p->opt = dns_resource_record_unref(p->opt);
- *ret_answer = answer;
- answer = NULL;
+ *ret_answer = TAKE_PTR(answer);
+
return 0;
}
@@ -2312,11 +2294,8 @@ int dns_packet_extract(DnsPacket *p) {
if (r < 0)
return r;
- p->question = question;
- question = NULL;
-
- p->answer = answer;
- answer = NULL;
+ p->question = TAKE_PTR(question);
+ p->answer = TAKE_PTR(answer);
p->extracted = true;
@@ -2351,6 +2330,31 @@ int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
return dns_resource_key_equal(p->question->keys[0], key);
}
+static void dns_packet_hash_func(const void *p, struct siphash *state) {
+ const DnsPacket *s = p;
+
+ assert(s);
+
+ siphash24_compress(&s->size, sizeof(s->size), state);
+ siphash24_compress(DNS_PACKET_DATA((DnsPacket*) s), s->size, state);
+}
+
+static int dns_packet_compare_func(const void *a, const void *b) {
+ const DnsPacket *x = a, *y = b;
+
+ if (x->size < y->size)
+ return -1;
+ if (x->size > y->size)
+ return 1;
+
+ return memcmp(DNS_PACKET_DATA((DnsPacket*) x), DNS_PACKET_DATA((DnsPacket*) y), x->size);
+}
+
+const struct hash_ops dns_packet_hash_ops = {
+ .hash = dns_packet_hash_func,
+ .compare = dns_packet_compare_func
+};
+
static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
[DNS_RCODE_SUCCESS] = "SUCCESS",
[DNS_RCODE_FORMERR] = "FORMERR",
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
index 15994d24b1..8e9d74a71a 100644
--- a/src/resolve/resolved-dns-packet.h
+++ b/src/resolve/resolved-dns-packet.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <netinet/ip.h>
@@ -283,6 +267,8 @@ DnsProtocol dns_protocol_from_string(const char *s) _pure_;
#define MDNS_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 251U) })
#define MDNS_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } })
+extern const struct hash_ops dns_packet_hash_ops;
+
static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) {
uint64_t f;
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index 5f51340743..c921fe841f 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "dns-domain.h"
@@ -638,8 +620,7 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
dns_query_reset_answer(q);
- q->answer = answer;
- answer = NULL;
+ q->answer = TAKE_PTR(answer);
q->answer_rcode = DNS_RCODE_SUCCESS;
q->answer_protocol = dns_synthesize_protocol(q->flags);
q->answer_family = dns_synthesize_family(q->flags);
@@ -668,8 +649,7 @@ static int dns_query_try_etc_hosts(DnsQuery *q) {
dns_query_reset_answer(q);
- q->answer = answer;
- answer = NULL;
+ q->answer = TAKE_PTR(answer);
q->answer_rcode = DNS_RCODE_SUCCESS;
q->answer_protocol = dns_synthesize_protocol(q->flags);
q->answer_family = dns_synthesize_family(q->flags);
@@ -994,12 +974,10 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname)
q->flags |= SD_RESOLVED_NO_SEARCH;
dns_question_unref(q->question_idna);
- q->question_idna = nq_idna;
- nq_idna = NULL;
+ q->question_idna = TAKE_PTR(nq_idna);
dns_question_unref(q->question_utf8);
- q->question_utf8 = nq_utf8;
- nq_utf8 = NULL;
+ q->question_utf8 = TAKE_PTR(nq_utf8);
dns_query_free_candidates(q);
dns_query_reset_answer(q);
diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h
index c01dc35777..5ee946bc75 100644
--- a/src/resolve/resolved-dns-query.h
+++ b/src/resolve/resolved-dns-query.h
@@ -1,26 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-
#include "sd-bus.h"
#include "set.h"
diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c
index 4dc3de4052..68fb3b9eac 100644
--- a/src/resolve/resolved-dns-question.c
+++ b/src/resolve/resolved-dns-question.c
@@ -1,29 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "dns-domain.h"
#include "dns-type.h"
#include "resolved-dns-question.h"
-DnsQuestion *dns_question_new(unsigned n) {
+DnsQuestion *dns_question_new(size_t n) {
DnsQuestion *q;
assert(n > 0);
@@ -54,7 +36,7 @@ DnsQuestion *dns_question_unref(DnsQuestion *q) {
assert(q->n_ref > 0);
if (q->n_ref == 1) {
- unsigned i;
+ size_t i;
for (i = 0; i < q->n_keys; i++)
dns_resource_key_unref(q->keys[i]);
@@ -66,7 +48,7 @@ DnsQuestion *dns_question_unref(DnsQuestion *q) {
}
int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
- unsigned i;
+ size_t i;
int r;
assert(key);
@@ -90,7 +72,7 @@ int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
}
int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
- unsigned i;
+ size_t i;
int r;
assert(rr);
@@ -108,7 +90,7 @@ int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *s
}
int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
- unsigned i;
+ size_t i;
int r;
assert(rr);
@@ -134,7 +116,7 @@ int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, c
int dns_question_is_valid_for_query(DnsQuestion *q) {
const char *name;
- unsigned i;
+ size_t i;
int r;
if (!q)
@@ -168,7 +150,7 @@ int dns_question_is_valid_for_query(DnsQuestion *q) {
}
int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
- unsigned j;
+ size_t j;
int r;
assert(k);
@@ -186,7 +168,7 @@ int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
}
int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
- unsigned j;
+ size_t j;
int r;
if (a == b)
@@ -278,8 +260,7 @@ int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname,
return r;
}
- *ret = n;
- n = NULL;
+ *ret = TAKE_PTR(n);
return 1;
}
@@ -348,8 +329,7 @@ int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bo
return r;
}
- *ret = q;
- q = NULL;
+ *ret = TAKE_PTR(q);
return 0;
}
@@ -384,8 +364,7 @@ int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_
if (r < 0)
return r;
- *ret = q;
- q = NULL;
+ *ret = TAKE_PTR(q);
return 0;
}
@@ -468,8 +447,7 @@ int dns_question_new_service(
return r;
}
- *ret = q;
- q = NULL;
+ *ret = TAKE_PTR(q);
return 0;
}
diff --git a/src/resolve/resolved-dns-question.h b/src/resolve/resolved-dns-question.h
index 666eb92b8d..f513bf0328 100644
--- a/src/resolve/resolved-dns-question.h
+++ b/src/resolve/resolved-dns-question.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct DnsQuestion DnsQuestion;
#include "macro.h"
@@ -29,11 +10,11 @@ typedef struct DnsQuestion DnsQuestion;
struct DnsQuestion {
unsigned n_ref;
- unsigned n_keys, n_allocated;
+ size_t n_keys, n_allocated;
DnsResourceKey* keys[0];
};
-DnsQuestion *dns_question_new(unsigned n);
+DnsQuestion *dns_question_new(size_t n);
DnsQuestion *dns_question_ref(DnsQuestion *q);
DnsQuestion *dns_question_unref(DnsQuestion *q);
@@ -53,7 +34,7 @@ int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname,
const char *dns_question_first_name(DnsQuestion *q);
-static inline unsigned dns_question_size(DnsQuestion *q) {
+static inline size_t dns_question_size(DnsQuestion *q) {
return q ? q->n_keys : 0;
}
@@ -64,7 +45,7 @@ static inline bool dns_question_isempty(DnsQuestion *q) {
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuestion*, dns_question_unref);
#define _DNS_QUESTION_FOREACH(u, key, q) \
- for (unsigned UNIQ_T(i, u) = ({ \
+ for (size_t UNIQ_T(i, u) = ({ \
(key) = ((q) && (q)->n_keys > 0) ? (q)->keys[0] : NULL; \
0; \
}); \
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index 4056bda558..cfd0ed214d 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <math.h>
@@ -349,7 +331,7 @@ char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t bu
snprintf(buf, buf_size, "%s %s%s%.0u %s%s%.0u",
dns_resource_key_name(key),
strempty(c), c ? "" : "CLASS", c ? 0 : key->class,
- strempty(t), t ? "" : "TYPE", t ? 0 : key->class);
+ strempty(t), t ? "" : "TYPE", t ? 0 : key->type);
return ans;
}
@@ -560,8 +542,7 @@ int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const u
if (!rr->ptr.name)
return -ENOMEM;
- *ret = rr;
- rr = NULL;
+ *ret = TAKE_PTR(rr);
return 0;
}
@@ -1246,7 +1227,6 @@ ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) {
*out = rr->tlsa.data;
return rr->tlsa.data_size;
-
case DNS_TYPE_OPENPGPKEY:
default:
*out = rr->generic.data;
@@ -1734,8 +1714,7 @@ DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) {
break;
}
- t = copy;
- copy = NULL;
+ t = TAKE_PTR(copy);
return t;
}
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index 8e1a6bb2dc..2f08b6119e 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <netinet/in.h>
@@ -100,7 +84,6 @@ struct DnsResourceKey {
._name = (char*) n, \
})
-
struct DnsTxtItem {
size_t length;
LIST_FIELDS(DnsTxtItem, items);
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index bf6aac8300..38ea7fea0a 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/tcp.h>
@@ -65,12 +47,18 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int
* not update it from the on, even if the setting
* changes. */
- if (l)
+ if (l) {
s->dnssec_mode = link_get_dnssec_mode(l);
- else
+ s->dns_over_tls_mode = link_get_dns_over_tls_mode(l);
+ } else {
s->dnssec_mode = manager_get_dnssec_mode(m);
- } else
+ s->dns_over_tls_mode = manager_get_dns_over_tls_mode(m);
+ }
+
+ } else {
s->dnssec_mode = DNSSEC_NO;
+ s->dns_over_tls_mode = DNS_OVER_TLS_NO;
+ }
LIST_PREPEND(scopes, m->dns_scopes, s);
@@ -234,7 +222,7 @@ static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
- if (!ratelimit_test(&s->ratelimit))
+ if (!ratelimit_below(&s->ratelimit))
return -EBUSY;
family = s->family;
@@ -259,7 +247,7 @@ static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
case DNS_PROTOCOL_MDNS:
assert(fd < 0);
- if (!ratelimit_test(&s->ratelimit))
+ if (!ratelimit_below(&s->ratelimit))
return -EBUSY;
family = s->family;
@@ -319,13 +307,14 @@ static int dns_scope_socket(
int family,
const union in_addr_union *address,
DnsServer *server,
- uint16_t port) {
+ uint16_t port,
+ union sockaddr_union *ret_socket_address) {
_cleanup_close_ int fd = -1;
- union sockaddr_union sa = {};
+ union sockaddr_union sa;
socklen_t salen;
static const int one = 1;
- int ret, r, ifindex;
+ int r, ifindex;
assert(s);
@@ -405,22 +394,27 @@ static int dns_scope_socket(
}
}
- r = connect(fd, &sa.sa, salen);
- if (r < 0 && errno != EINPROGRESS)
- return -errno;
-
- ret = fd;
- fd = -1;
+ if (ret_socket_address)
+ *ret_socket_address = sa;
+ else {
+ r = connect(fd, &sa.sa, salen);
+ if (r < 0 && errno != EINPROGRESS)
+ return -errno;
+ }
- return ret;
+ return TAKE_FD(fd);
}
int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port) {
- return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, server, port);
+ return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, server, port, NULL);
}
-int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port) {
- return dns_scope_socket(s, SOCK_STREAM, family, address, server, port);
+int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port, union sockaddr_union *ret_socket_address) {
+ /* If ret_socket_address is not NULL, the caller is responisble
+ * for calling connect() or sendmsg(). This is required by TCP
+ * Fast Open, to be able to send the initial SYN packet along
+ * with the first data packet. */
+ return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address);
}
DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
@@ -684,8 +678,7 @@ int dns_scope_make_reply_packet(
return r;
DNS_PACKET_HEADER(p)->arcount = htobe16(dns_answer_size(soa));
- *ret = p;
- p = NULL;
+ *ret = TAKE_PTR(p);
return 0;
}
@@ -776,7 +769,7 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
} else {
int fd;
- if (!ratelimit_test(&s->ratelimit))
+ if (!ratelimit_below(&s->ratelimit))
return;
if (p->family == AF_INET)
@@ -869,8 +862,7 @@ static int dns_scope_make_conflict_packet(
if (r < 0)
return r;
- *ret = p;
- p = NULL;
+ *ret = TAKE_PTR(p);
return 0;
}
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index 6f58c3c257..04e93f8f73 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "list.h"
typedef struct DnsScope DnsScope;
@@ -48,6 +29,7 @@ struct DnsScope {
DnsProtocol protocol;
int family;
DnssecMode dnssec_mode;
+ DnsOverTlsMode dns_over_tls_mode;
Link *link;
@@ -88,7 +70,7 @@ void dns_scope_packet_received(DnsScope *s, usec_t rtt);
void dns_scope_packet_lost(DnsScope *s, usec_t usec);
int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p);
-int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port);
+int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port, union sockaddr_union *ret_socket_address);
int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port);
DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain);
diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c
index 585c518e19..c3817acf11 100644
--- a/src/resolve/resolved-dns-search-domain.c
+++ b/src/resolve/resolved-dns-search-domain.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "dns-domain.h"
@@ -56,8 +38,7 @@ int dns_search_domain_new(
d->n_ref = 1;
d->manager = m;
d->type = type;
- d->name = normalized;
- normalized = NULL;
+ d->name = TAKE_PTR(normalized);
switch (type) {
diff --git a/src/resolve/resolved-dns-search-domain.h b/src/resolve/resolved-dns-search-domain.h
index 8442fbd7da..d0c2914d36 100644
--- a/src/resolve/resolved-dns-search-domain.h
+++ b/src/resolve/resolved-dns-search-domain.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "macro.h"
typedef struct DnsSearchDomain DnsSearchDomain;
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 68c5d5c1e3..5476ca2dbd 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-messages.h"
@@ -28,10 +10,6 @@
#include "string-table.h"
#include "string-util.h"
-/* After how much time to repeat classic DNS requests */
-#define DNS_TIMEOUT_MIN_USEC (750 * USEC_PER_MSEC)
-#define DNS_TIMEOUT_MAX_USEC (SD_RESOLVED_QUERY_TIMEOUT_USEC / DNS_TRANSACTION_ATTEMPTS_MAX)
-
/* The amount of time to wait before retrying with a full feature set */
#define DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC (6 * USEC_PER_HOUR)
#define DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC (5 * USEC_PER_MINUTE)
@@ -102,6 +80,11 @@ int dns_server_new(
s->linked = true;
+#if ENABLE_DNS_OVER_TLS
+ /* Do not verify cerificate */
+ gnutls_certificate_allocate_credentials(&s->tls_cert_cred);
+#endif
+
/* A new DNS server that isn't fallback is added and the one
* we used so far was a fallback one? Then let's try to pick
* the new one */
@@ -136,6 +119,16 @@ DnsServer* dns_server_unref(DnsServer *s) {
if (s->n_ref > 0)
return NULL;
+ dns_stream_unref(s->stream);
+
+#if ENABLE_DNS_OVER_TLS
+ if (s->tls_cert_cred)
+ gnutls_certificate_free_credentials(s->tls_cert_cred);
+
+ if (s->tls_session_data.data)
+ gnutls_free(s->tls_session_data.data);
+#endif
+
free(s->server_string);
return mfree(s);
}
@@ -247,6 +240,7 @@ static void dns_server_reset_counters(DnsServer *s) {
s->n_failed_udp = 0;
s->n_failed_tcp = 0;
+ s->n_failed_tls = 0;
s->packet_truncated = false;
s->verified_usec = 0;
@@ -262,34 +256,37 @@ static void dns_server_reset_counters(DnsServer *s) {
* incomplete. */
}
-void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size) {
+void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, size_t size) {
assert(s);
if (protocol == IPPROTO_UDP) {
if (s->possible_feature_level == level)
s->n_failed_udp = 0;
-
- /* If the RRSIG data is missing, then we can only validate EDNS0 at max */
- if (s->packet_rrsig_missing && level >= DNS_SERVER_FEATURE_LEVEL_DO)
- level = DNS_SERVER_FEATURE_LEVEL_DO - 1;
-
- /* If the OPT RR got lost, then we can only validate UDP at max */
- if (s->packet_bad_opt && level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
- level = DNS_SERVER_FEATURE_LEVEL_EDNS0 - 1;
-
- /* Even if we successfully receive a reply to a request announcing support for large packets,
- that does not mean we can necessarily receive large packets. */
- if (level == DNS_SERVER_FEATURE_LEVEL_LARGE)
- level = DNS_SERVER_FEATURE_LEVEL_LARGE - 1;
-
} else if (protocol == IPPROTO_TCP) {
+ if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(level)) {
+ if (s->possible_feature_level == level)
+ s->n_failed_tls = 0;
+ } else {
+ if (s->possible_feature_level == level)
+ s->n_failed_tcp = 0;
+
+ /* Successful TCP connections are only useful to verify the TCP feature level. */
+ level = DNS_SERVER_FEATURE_LEVEL_TCP;
+ }
+ }
- if (s->possible_feature_level == level)
- s->n_failed_tcp = 0;
+ /* If the RRSIG data is missing, then we can only validate EDNS0 at max */
+ if (s->packet_rrsig_missing && level >= DNS_SERVER_FEATURE_LEVEL_DO)
+ level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0;
- /* Successful TCP connections are only useful to verify the TCP feature level. */
- level = DNS_SERVER_FEATURE_LEVEL_TCP;
- }
+ /* If the OPT RR got lost, then we can only validate UDP at max */
+ if (s->packet_bad_opt && level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
+ level = DNS_SERVER_FEATURE_LEVEL_EDNS0 - 1;
+
+ /* Even if we successfully receive a reply to a request announcing support for large packets,
+ that does not mean we can necessarily receive large packets. */
+ if (level == DNS_SERVER_FEATURE_LEVEL_LARGE)
+ level = DNS_SERVER_FEATURE_LEVEL_LARGE - 1;
dns_server_verified(s, level);
@@ -298,31 +295,22 @@ void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLeve
this size. */
if (protocol == IPPROTO_UDP && s->received_udp_packet_max < size)
s->received_udp_packet_max = size;
-
- if (s->max_rtt < rtt) {
- s->max_rtt = rtt;
- s->resend_timeout = CLAMP(s->max_rtt * 2, DNS_TIMEOUT_MIN_USEC, DNS_TIMEOUT_MAX_USEC);
- } else if (s->resend_timeout > rtt)
- /* If we received the packet faster than the resend_timeout, bias
- * the resend_timeout back to the rtt. */
- s->resend_timeout = CLAMP((2 * s->resend_timeout + rtt) / 3, DNS_TIMEOUT_MIN_USEC, DNS_TIMEOUT_MAX_USEC);
}
-void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t usec) {
+void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level) {
assert(s);
assert(s->manager);
if (s->possible_feature_level == level) {
if (protocol == IPPROTO_UDP)
s->n_failed_udp++;
- else if (protocol == IPPROTO_TCP)
- s->n_failed_tcp++;
+ else if (protocol == IPPROTO_TCP) {
+ if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(level))
+ s->n_failed_tls++;
+ else
+ s->n_failed_tcp++;
+ }
}
-
- if (s->resend_timeout > usec)
- return;
-
- s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC);
}
void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level) {
@@ -344,7 +332,7 @@ void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level)
/* If the RRSIG RRs are missing, we have to downgrade what we previously verified */
if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO)
- s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_DO-1;
+ s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0;
s->packet_rrsig_missing = true;
}
@@ -406,9 +394,14 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
/* Determine the best feature level we care about. If DNSSEC mode is off there's no point in using anything
* better than EDNS0, hence don't even try. */
- best = dns_server_get_dnssec_mode(s) == DNSSEC_NO ?
- DNS_SERVER_FEATURE_LEVEL_EDNS0 :
- DNS_SERVER_FEATURE_LEVEL_BEST;
+ if (dns_server_get_dnssec_mode(s) != DNSSEC_NO)
+ best = dns_server_get_dns_over_tls_mode(s) == DNS_OVER_TLS_NO ?
+ DNS_SERVER_FEATURE_LEVEL_LARGE :
+ DNS_SERVER_FEATURE_LEVEL_TLS_DO;
+ else
+ best = dns_server_get_dns_over_tls_mode(s) == DNS_OVER_TLS_NO ?
+ DNS_SERVER_FEATURE_LEVEL_EDNS0 :
+ DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN;
/* Clamp the feature level the highest level we care about. The DNSSEC mode might have changed since the last
* time, hence let's downgrade if we are still at a higher level. */
@@ -442,7 +435,14 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
* work. Upgrade back to UDP again. */
log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
+ } else if (s->n_failed_tls > 0 &&
+ DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level)) {
+
+ /* We tried to connect using DNS-over-TLS, and it didn't work. Downgrade to plaintext UDP
+ * if we don't require DNS-over-TLS */
+ log_debug("Server doesn't support DNS-over-TLS, downgrading protocol...");
+ s->possible_feature_level--;
} else if (s->packet_bad_opt &&
s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
@@ -463,7 +463,7 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
* not. */
log_debug("Detected server responses lack RRSIG records, downgrading feature level...");
- s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0;
+ s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0;
} else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
s->possible_feature_level >= (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
@@ -588,8 +588,7 @@ void dns_server_warn_downgrade(DnsServer *server) {
"MESSAGE_ID=" SD_MESSAGE_DNSSEC_DOWNGRADE_STR,
LOG_MESSAGE("Server %s does not support DNSSEC, downgrading to non-DNSSEC mode.", dns_server_string(server)),
"DNS_SERVER=%s", dns_server_string(server),
- "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(server->possible_feature_level),
- NULL);
+ "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(server->possible_feature_level));
server->warned_downgrade = true;
}
@@ -807,6 +806,15 @@ DnssecMode dns_server_get_dnssec_mode(DnsServer *s) {
return manager_get_dnssec_mode(s->manager);
}
+DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s) {
+ assert(s);
+
+ if (s->link)
+ return link_get_dns_over_tls_mode(s->link);
+
+ return manager_get_dns_over_tls_mode(s->manager);
+}
+
void dns_server_flush_cache(DnsServer *s) {
DnsServer *current;
DnsScope *scope;
@@ -829,9 +837,6 @@ void dns_server_flush_cache(DnsServer *s) {
void dns_server_reset_features(DnsServer *s) {
assert(s);
- s->max_rtt = 0;
- s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
-
s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
@@ -916,7 +921,9 @@ static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVE
[DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP",
[DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP",
[DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0",
+ [DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN] = "TLS+EDNS0",
[DNS_SERVER_FEATURE_LEVEL_DO] = "UDP+EDNS0+DO",
[DNS_SERVER_FEATURE_LEVEL_LARGE] = "UDP+EDNS0+DO+LARGE",
+ [DNS_SERVER_FEATURE_LEVEL_TLS_DO] = "TLS+EDNS0+D0",
};
DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel);
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
index acc9281b12..dffc4217d1 100644
--- a/src/resolve/resolved-dns-server.h
+++ b/src/resolve/resolved-dns-server.h
@@ -1,27 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "in-addr-util.h"
+#if ENABLE_DNS_OVER_TLS
+#include <gnutls/gnutls.h>
+#endif
+
typedef struct DnsServer DnsServer;
typedef enum DnsServerType {
@@ -38,14 +23,17 @@ typedef enum DnsServerFeatureLevel {
DNS_SERVER_FEATURE_LEVEL_TCP,
DNS_SERVER_FEATURE_LEVEL_UDP,
DNS_SERVER_FEATURE_LEVEL_EDNS0,
+ DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN,
DNS_SERVER_FEATURE_LEVEL_DO,
DNS_SERVER_FEATURE_LEVEL_LARGE,
+ DNS_SERVER_FEATURE_LEVEL_TLS_DO,
_DNS_SERVER_FEATURE_LEVEL_MAX,
_DNS_SERVER_FEATURE_LEVEL_INVALID = -1
} DnsServerFeatureLevel;
#define DNS_SERVER_FEATURE_LEVEL_WORST 0
#define DNS_SERVER_FEATURE_LEVEL_BEST (_DNS_SERVER_FEATURE_LEVEL_MAX - 1)
+#define DNS_SERVER_FEATURE_LEVEL_IS_TLS(x) IN_SET(x, DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN, DNS_SERVER_FEATURE_LEVEL_TLS_DO)
const char* dns_server_feature_level_to_string(int i) _const_;
int dns_server_feature_level_from_string(const char *s) _pure_;
@@ -66,9 +54,12 @@ struct DnsServer {
int ifindex; /* for IPv6 link-local DNS servers */
char *server_string;
+ DnsStream *stream;
- usec_t resend_timeout;
- usec_t max_rtt;
+#if ENABLE_DNS_OVER_TLS
+ gnutls_certificate_credentials_t tls_cert_cred;
+ gnutls_datum_t tls_session_data;
+#endif
DnsServerFeatureLevel verified_feature_level;
DnsServerFeatureLevel possible_feature_level;
@@ -77,6 +68,7 @@ struct DnsServer {
unsigned n_failed_udp;
unsigned n_failed_tcp;
+ unsigned n_failed_tls;
bool packet_truncated:1;
bool packet_bad_opt:1;
@@ -111,8 +103,8 @@ DnsServer* dns_server_unref(DnsServer *s);
void dns_server_unlink(DnsServer *s);
void dns_server_move_back_and_unmark(DnsServer *s);
-void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t rtt, size_t size);
-void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t usec);
+void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, size_t size);
+void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level);
void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level);
void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level);
void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level);
@@ -146,6 +138,7 @@ void manager_next_dns_server(Manager *m);
bool dns_server_address_valid(int family, const union in_addr_union *sa);
DnssecMode dns_server_get_dnssec_mode(DnsServer *s);
+DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref);
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index 52f23cd864..066daef96e 100644
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/tcp.h>
@@ -29,6 +11,8 @@
#define DNS_STREAM_TIMEOUT_USEC (10 * USEC_PER_SEC)
#define DNS_STREAMS_MAX 128
+#define WRITE_TLS_DATA 1
+
static void dns_stream_stop(DnsStream *s) {
assert(s);
@@ -44,6 +28,13 @@ static int dns_stream_update_io(DnsStream *s) {
if (s->write_packet && s->n_written < sizeof(s->write_size) + s->write_packet->size)
f |= EPOLLOUT;
+ else if (!ordered_set_isempty(s->write_queue)) {
+ dns_packet_unref(s->write_packet);
+ s->write_packet = ordered_set_steal_first(s->write_queue);
+ s->write_size = htobe16(s->write_packet->size);
+ s->n_written = 0;
+ f |= EPOLLOUT;
+ }
if (!s->read_packet || s->n_read < sizeof(s->read_size) + s->read_packet->size)
f |= EPOLLIN;
@@ -53,7 +44,19 @@ static int dns_stream_update_io(DnsStream *s) {
static int dns_stream_complete(DnsStream *s, int error) {
assert(s);
- dns_stream_stop(s);
+#if ENABLE_DNS_OVER_TLS
+ if (s->tls_session && IN_SET(error, ETIMEDOUT, 0)) {
+ int r;
+
+ r = gnutls_bye(s->tls_session, GNUTLS_SHUT_RDWR);
+ if (r == GNUTLS_E_AGAIN && !s->tls_bye) {
+ dns_stream_ref(s); /* keep reference for closing TLS session */
+ s->tls_bye = true;
+ } else
+ dns_stream_stop(s);
+ } else
+#endif
+ dns_stream_stop(s);
if (s->complete)
s->complete(s, error);
@@ -188,6 +191,121 @@ static int dns_stream_identify(DnsStream *s) {
return 0;
}
+static ssize_t dns_stream_writev(DnsStream *s, const struct iovec *iov, size_t iovcnt, int flags) {
+ ssize_t r;
+
+ assert(s);
+ assert(iov);
+
+#if ENABLE_DNS_OVER_TLS
+ if (s->tls_session && !(flags & WRITE_TLS_DATA)) {
+ ssize_t ss;
+ size_t i;
+
+ r = 0;
+ for (i = 0; i < iovcnt; i++) {
+ ss = gnutls_record_send(s->tls_session, iov[i].iov_base, iov[i].iov_len);
+ if (ss < 0) {
+ switch(ss) {
+
+ case GNUTLS_E_INTERRUPTED:
+ return -EINTR;
+ case GNUTLS_E_AGAIN:
+ return -EAGAIN;
+ default:
+ log_debug("Failed to invoke gnutls_record_send: %s", gnutls_strerror(ss));
+ return -EIO;
+ }
+ }
+
+ r += ss;
+ if (ss != (ssize_t) iov[i].iov_len)
+ continue;
+ }
+ } else
+#endif
+ if (s->tfo_salen > 0) {
+ struct msghdr hdr = {
+ .msg_iov = (struct iovec*) iov,
+ .msg_iovlen = iovcnt,
+ .msg_name = &s->tfo_address.sa,
+ .msg_namelen = s->tfo_salen
+ };
+
+ r = sendmsg(s->fd, &hdr, MSG_FASTOPEN);
+ if (r < 0) {
+ if (errno == EOPNOTSUPP) {
+ s->tfo_salen = 0;
+ r = connect(s->fd, &s->tfo_address.sa, s->tfo_salen);
+ if (r < 0)
+ return -errno;
+
+ r = -EAGAIN;
+ } else if (errno == EINPROGRESS)
+ r = -EAGAIN;
+ } else
+ s->tfo_salen = 0; /* connection is made */
+ } else {
+ r = writev(s->fd, iov, iovcnt);
+ if (r < 0)
+ r = -errno;
+ }
+
+ return r;
+}
+
+static ssize_t dns_stream_read(DnsStream *s, void *buf, size_t count) {
+ ssize_t ss;
+
+#if ENABLE_DNS_OVER_TLS
+ if (s->tls_session) {
+ ss = gnutls_record_recv(s->tls_session, buf, count);
+ if (ss < 0) {
+ switch(ss) {
+
+ case GNUTLS_E_INTERRUPTED:
+ return -EINTR;
+ case GNUTLS_E_AGAIN:
+ return -EAGAIN;
+ default:
+ log_debug("Failed to invoke gnutls_record_send: %s", gnutls_strerror(ss));
+ return -EIO;
+ }
+ } else if (s->on_connection) {
+ int r;
+
+ r = s->on_connection(s);
+ s->on_connection = NULL; /* only call once */
+ if (r < 0)
+ return r;
+ }
+ } else
+#endif
+ {
+ ss = read(s->fd, buf, count);
+ if (ss < 0)
+ ss = -errno;
+ }
+
+ return ss;
+}
+
+#if ENABLE_DNS_OVER_TLS
+static ssize_t dns_stream_tls_writev(gnutls_transport_ptr_t p, const giovec_t * iov, int iovcnt) {
+ int r;
+
+ assert(p);
+
+ r = dns_stream_writev((DnsStream*) p, (struct iovec*) iov, iovcnt, WRITE_TLS_DATA);
+ if (r < 0) {
+ errno = -r;
+ return -1;
+ }
+
+ return r;
+}
+#endif
+
static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) {
DnsStream *s = userdata;
@@ -202,9 +320,46 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
assert(s);
- r = dns_stream_identify(s);
- if (r < 0)
- return dns_stream_complete(s, -r);
+#if ENABLE_DNS_OVER_TLS
+ if (s->tls_bye) {
+ assert(s->tls_session);
+
+ r = gnutls_bye(s->tls_session, GNUTLS_SHUT_RDWR);
+ if (r != GNUTLS_E_AGAIN) {
+ s->tls_bye = false;
+ dns_stream_unref(s);
+ }
+
+ return 0;
+ }
+
+ if (s->tls_handshake < 0) {
+ assert(s->tls_session);
+
+ s->tls_handshake = gnutls_handshake(s->tls_session);
+ if (s->tls_handshake >= 0) {
+ if (s->on_connection && !(gnutls_session_get_flags(s->tls_session) & GNUTLS_SFLAGS_FALSE_START)) {
+ r = s->on_connection(s);
+ s->on_connection = NULL; /* only call once */
+ if (r < 0)
+ return r;
+ }
+ } else {
+ if (gnutls_error_is_fatal(s->tls_handshake))
+ return dns_stream_complete(s, ECONNREFUSED);
+ else
+ return 0;
+ }
+
+ }
+#endif
+
+ /* only identify after connecting */
+ if (s->tfo_salen == 0) {
+ r = dns_stream_identify(s);
+ if (r < 0)
+ return dns_stream_complete(s, -r);
+ }
if ((revents & EPOLLOUT) &&
s->write_packet &&
@@ -220,10 +375,10 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
IOVEC_INCREMENT(iov, 2, s->n_written);
- ss = writev(fd, iov, 2);
+ ss = dns_stream_writev(s, iov, 2, 0);
if (ss < 0) {
- if (!IN_SET(errno, EINTR, EAGAIN))
- return dns_stream_complete(s, errno);
+ if (!IN_SET(-ss, EINTR, EAGAIN))
+ return dns_stream_complete(s, -ss);
} else
s->n_written += ss;
@@ -242,10 +397,10 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
if (s->n_read < sizeof(s->read_size)) {
ssize_t ss;
- ss = read(fd, (uint8_t*) &s->read_size + s->n_read, sizeof(s->read_size) - s->n_read);
+ ss = dns_stream_read(s, (uint8_t*) &s->read_size + s->n_read, sizeof(s->read_size) - s->n_read);
if (ss < 0) {
- if (!IN_SET(errno, EINTR, EAGAIN))
- return dns_stream_complete(s, errno);
+ if (!IN_SET(-ss, EINTR, EAGAIN))
+ return dns_stream_complete(s, -ss);
} else if (ss == 0)
return dns_stream_complete(s, ECONNRESET);
else
@@ -290,7 +445,7 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
}
}
- ss = read(fd,
+ ss = dns_stream_read(s,
(uint8_t*) DNS_PACKET_DATA(s->read_packet) + s->n_read - sizeof(s->read_size),
sizeof(s->read_size) + be16toh(s->read_size) - s->n_read);
if (ss < 0) {
@@ -304,15 +459,18 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
/* Are we done? If so, disable the event source for EPOLLIN */
if (s->n_read >= sizeof(s->read_size) + be16toh(s->read_size)) {
- r = dns_stream_update_io(s);
- if (r < 0)
- return dns_stream_complete(s, -r);
-
/* If there's a packet handler
* installed, call that. Note that
* this is optional... */
- if (s->on_packet)
- return s->on_packet(s);
+ if (s->on_packet) {
+ r = s->on_packet(s);
+ if (r < 0)
+ return r;
+ }
+
+ r = dns_stream_update_io(s);
+ if (r < 0)
+ return dns_stream_complete(s, -r);
}
}
}
@@ -325,6 +483,9 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
}
DnsStream *dns_stream_unref(DnsStream *s) {
+ DnsPacket *p;
+ Iterator i;
+
if (!s)
return NULL;
@@ -336,19 +497,31 @@ DnsStream *dns_stream_unref(DnsStream *s) {
dns_stream_stop(s);
+ if (s->server && s->server->stream == s)
+ s->server->stream = NULL;
+
if (s->manager) {
LIST_REMOVE(streams, s->manager->dns_streams, s);
s->manager->n_dns_streams--;
}
+#if ENABLE_DNS_OVER_TLS
+ if (s->tls_session)
+ gnutls_deinit(s->tls_session);
+#endif
+
+ ORDERED_SET_FOREACH(p, s->write_queue, i)
+ dns_packet_unref(ordered_set_remove(s->write_queue, p));
+
dns_packet_unref(s->write_packet);
dns_packet_unref(s->read_packet);
+ dns_server_unref(s->server);
+
+ ordered_set_free(s->write_queue);
return mfree(s);
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref);
-
DnsStream *dns_stream_ref(DnsStream *s) {
if (!s)
return NULL;
@@ -359,7 +532,7 @@ DnsStream *dns_stream_ref(DnsStream *s) {
return s;
}
-int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
+int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd, const union sockaddr_union *tfo_address) {
_cleanup_(dns_stream_unrefp) DnsStream *s = NULL;
int r;
@@ -373,6 +546,10 @@ int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
if (!s)
return -ENOMEM;
+ r = ordered_set_ensure_allocated(&s->write_queue, &dns_packet_hash_ops);
+ if (r < 0)
+ return r;
+
s->n_ref = 1;
s->fd = -1;
s->protocol = protocol;
@@ -397,23 +574,43 @@ int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
LIST_PREPEND(streams, m->dns_streams, s);
s->manager = m;
s->fd = fd;
+ if (tfo_address) {
+ s->tfo_address = *tfo_address;
+ s->tfo_salen = tfo_address->sa.sa_family == AF_INET6 ? sizeof(tfo_address->in6) : sizeof(tfo_address->in);
+ }
+
m->n_dns_streams++;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
+
+ return 0;
+}
+
+#if ENABLE_DNS_OVER_TLS
+int dns_stream_connect_tls(DnsStream *s, gnutls_session_t tls_session) {
+ gnutls_transport_set_ptr2(tls_session, (gnutls_transport_ptr_t) (long) s->fd, s);
+ gnutls_transport_set_vec_push_function(tls_session, &dns_stream_tls_writev);
+
+ s->encrypted = true;
+ s->tls_session = tls_session;
+ s->tls_handshake = gnutls_handshake(tls_session);
+ if (s->tls_handshake < 0 && gnutls_error_is_fatal(s->tls_handshake))
+ return -ECONNREFUSED;
return 0;
}
+#endif
int dns_stream_write_packet(DnsStream *s, DnsPacket *p) {
+ int r;
+
assert(s);
- if (s->write_packet)
- return -EBUSY;
+ r = ordered_set_put(s->write_queue, p);
+ if (r < 0)
+ return r;
- s->write_packet = dns_packet_ref(p);
- s->write_size = htobe16(p->size);
- s->n_written = 0;
+ dns_packet_ref(p);
return dns_stream_update_io(s);
}
diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h
index e099158e1e..9a0da226d8 100644
--- a/src/resolve/resolved-dns-stream.h
+++ b/src/resolve/resolved-dns-stream.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "socket-util.h"
typedef struct DnsStream DnsStream;
@@ -28,6 +9,10 @@ typedef struct DnsStream DnsStream;
#include "resolved-dns-transaction.h"
#include "resolved-manager.h"
+#if ENABLE_DNS_OVER_TLS
+#include <gnutls/gnutls.h>
+#endif
+
/* Streams are used by three subsystems:
*
* 1. The normal transaction logic when doing a DNS or LLMNR lookup via TCP
@@ -50,26 +35,47 @@ struct DnsStream {
uint32_t ttl;
bool identified;
+ /* only when using TCP fast open */
+ union sockaddr_union tfo_address;
+ socklen_t tfo_salen;
+
+#if ENABLE_DNS_OVER_TLS
+ gnutls_session_t tls_session;
+ int tls_handshake;
+ bool tls_bye;
+#endif
+
sd_event_source *io_event_source;
sd_event_source *timeout_event_source;
be16_t write_size, read_size;
DnsPacket *write_packet, *read_packet;
size_t n_written, n_read;
+ OrderedSet *write_queue;
+ int (*on_connection)(DnsStream *s);
int (*on_packet)(DnsStream *s);
int (*complete)(DnsStream *s, int error);
- DnsTransaction *transaction; /* when used by the transaction logic */
+ LIST_HEAD(DnsTransaction, transactions); /* when used by the transaction logic */
+ DnsServer *server; /* when used by the transaction logic */
DnsQuery *query; /* when used by the DNS stub logic */
+ /* used when DNS-over-TLS is enabled */
+ bool encrypted:1;
+
LIST_FIELDS(DnsStream, streams);
};
-int dns_stream_new(Manager *m, DnsStream **s, DnsProtocol protocol, int fd);
+int dns_stream_new(Manager *m, DnsStream **s, DnsProtocol protocol, int fd, const union sockaddr_union *tfo_address);
+#if ENABLE_DNS_OVER_TLS
+int dns_stream_connect_tls(DnsStream *s, gnutls_session_t tls_session);
+#endif
DnsStream *dns_stream_unref(DnsStream *s);
DnsStream *dns_stream_ref(DnsStream *s);
+DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref);
+
int dns_stream_write_packet(DnsStream *s, DnsPacket *p);
static inline bool DNS_STREAM_QUEUED(DnsStream *s) {
diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c
index 5ce8d240dd..5ddf13081e 100644
--- a/src/resolve/resolved-dns-stub.c
+++ b/src/resolve/resolved-dns-stub.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "fd-util.h"
#include "resolved-dns-stub.h"
@@ -447,10 +429,8 @@ static int manager_dns_stub_udp_fd(Manager *m) {
return r;
(void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp");
- m->dns_stub_udp_fd = fd;
- fd = -1;
- return m->dns_stub_udp_fd;
+ return m->dns_stub_udp_fd = TAKE_FD(fd);
}
static int on_dns_stub_stream_packet(DnsStream *s) {
@@ -484,7 +464,7 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void
return -errno;
}
- r = dns_stream_new(m, &stream, DNS_PROTOCOL_DNS, cfd);
+ r = dns_stream_new(m, &stream, DNS_PROTOCOL_DNS, cfd, NULL);
if (r < 0) {
safe_close(cfd);
return r;
@@ -542,10 +522,8 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
return r;
(void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp");
- m->dns_stub_tcp_fd = fd;
- fd = -1;
- return m->dns_stub_tcp_fd;
+ return m->dns_stub_tcp_fd = TAKE_FD(fd);
}
int manager_dns_stub_start(Manager *m) {
diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h
index 197f2cc758..f34e9db1af 100644
--- a/src/resolve/resolved-dns-stub.h
+++ b/src/resolve/resolved-dns-stub.h
@@ -1,29 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "resolved-manager.h"
-/* 127.0.0.53 in native endian */
-#define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U)
-
void manager_dns_stub_stop(Manager *m);
int manager_dns_stub_start(Manager *m);
diff --git a/src/resolve/resolved-dns-synthesize.c b/src/resolve/resolved-dns-synthesize.c
index e71fcbdcca..9a8ce7ae2d 100644
--- a/src/resolve/resolved-dns-synthesize.c
+++ b/src/resolve/resolved-dns-synthesize.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "hostname-util.h"
@@ -440,10 +422,8 @@ int dns_synthesize_answer(
if (found) {
- if (ret) {
- *ret = answer;
- answer = NULL;
- }
+ if (ret)
+ *ret = TAKE_PTR(answer);
return 1;
} else if (nxdomain)
diff --git a/src/resolve/resolved-dns-synthesize.h b/src/resolve/resolved-dns-synthesize.h
index 385863786f..0d9d17bac7 100644
--- a/src/resolve/resolved-dns-synthesize.h
+++ b/src/resolve/resolved-dns-synthesize.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "resolved-dns-answer.h"
#include "resolved-dns-question.h"
#include "resolved-manager.h"
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index f4bbde0219..c60b8215a6 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-messages.h"
@@ -31,9 +13,16 @@
#include "resolved-llmnr.h"
#include "string-table.h"
+#if ENABLE_DNS_OVER_TLS
+#include <gnutls/socket.h>
+#endif
+
#define TRANSACTIONS_MAX 4096
#define TRANSACTION_TCP_TIMEOUT_USEC (10U*USEC_PER_SEC)
+/* After how much time to repeat classic DNS requests */
+#define DNS_TIMEOUT_USEC (SD_RESOLVED_QUERY_TIMEOUT_USEC / DNS_TRANSACTION_ATTEMPTS_MAX)
+
static void dns_transaction_reset_answer(DnsTransaction *t) {
assert(t);
@@ -64,9 +53,11 @@ static void dns_transaction_close_connection(DnsTransaction *t) {
if (t->stream) {
/* Let's detach the stream from our transaction, in case something else keeps a reference to it. */
- t->stream->complete = NULL;
- t->stream->on_packet = NULL;
- t->stream->transaction = NULL;
+ LIST_REMOVE(transactions_by_stream, t->stream->transactions, t);
+
+ /* Remove packet in case it's still in the queue */
+ dns_packet_unref(ordered_set_remove(t->stream->write_queue, t->sent));
+
t->stream = dns_stream_unref(t->stream);
}
@@ -326,8 +317,7 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
"DNS_QUESTION=%s", key_str,
"DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result),
"DNS_SERVER=%s", dns_server_string(t->server),
- "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level),
- NULL);
+ "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level));
}
/* Note that this call might invalidate the query. Callers
@@ -462,42 +452,33 @@ static int dns_transaction_maybe_restart(DnsTransaction *t) {
return 1;
}
-static int on_stream_complete(DnsStream *s, int error) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- DnsTransaction *t;
-
- assert(s);
- assert(s->transaction);
-
- /* Copy the data we care about out of the stream before we
- * destroy it. */
- t = s->transaction;
- p = dns_packet_ref(s->read_packet);
+static void on_transaction_stream_error(DnsTransaction *t, int error) {
+ assert(t);
dns_transaction_close_connection(t);
if (ERRNO_IS_DISCONNECT(error)) {
- usec_t usec;
-
if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
/* If the LLMNR/TCP connection failed, the host doesn't support LLMNR, and we cannot answer the
* question on this scope. */
dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND);
- return 0;
+ return;
}
- log_debug_errno(error, "Connection failure for DNS TCP stream: %m");
- assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
- dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level, usec - t->start_usec);
-
dns_transaction_retry(t, true);
- return 0;
+ return;
}
if (error != 0) {
t->answer_errno = error;
dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
- return 0;
}
+}
+
+static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
+ assert(t);
+ assert(p);
+
+ dns_transaction_close_connection(t);
if (dns_packet_validate_reply(p) <= 0) {
log_debug("Invalid TCP reply packet.");
@@ -522,9 +503,83 @@ static int on_stream_complete(DnsStream *s, int error) {
return 0;
}
-static int dns_transaction_open_tcp(DnsTransaction *t) {
+static int on_stream_connection(DnsStream *s) {
+#if ENABLE_DNS_OVER_TLS
+ /* Store TLS Ticket for faster succesive TLS handshakes */
+ if (s->tls_session && s->server) {
+ if (s->server->tls_session_data.data)
+ gnutls_free(s->server->tls_session_data.data);
+
+ gnutls_session_get_data2(s->tls_session, &s->server->tls_session_data);
+ }
+#endif
+
+ return 0;
+}
+
+static int on_stream_complete(DnsStream *s, int error) {
+ DnsTransaction *t, *n;
+ int r = 0;
+
+ /* Do not let new transactions use this stream */
+ if (s->server && s->server->stream == s)
+ s->server->stream = dns_stream_unref(s->server->stream);
+
+ if (ERRNO_IS_DISCONNECT(error) && s->protocol != DNS_PROTOCOL_LLMNR) {
+ usec_t usec;
+
+ log_debug_errno(error, "Connection failure for DNS TCP stream: %m");
+
+ if (s->transactions) {
+ t = s->transactions;
+ assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
+ dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level);
+ }
+ }
+
+ LIST_FOREACH_SAFE(transactions_by_stream, t, n, s->transactions)
+ if (error != 0)
+ on_transaction_stream_error(t, error);
+ else if (DNS_PACKET_ID(s->read_packet) == t->id)
+ /* As each transaction have a unique id the return code is only set once */
+ r = dns_transaction_on_stream_packet(t, s->read_packet);
+
+ return r;
+}
+
+static int dns_stream_on_packet(DnsStream *s) {
+ _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+ int r = 0;
+ DnsTransaction *t;
+
+ /* Take ownership of packet to be able to receive new packets */
+ p = TAKE_PTR(s->read_packet);
+ s->n_read = 0;
+
+ t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
+
+ /* Ignore incorrect transaction id as transaction can have been canceled */
+ if (t)
+ r = dns_transaction_on_stream_packet(t, p);
+ else {
+ if (dns_packet_validate_reply(p) <= 0) {
+ log_debug("Invalid TCP reply packet.");
+ on_stream_complete(s, 0);
+ }
+ return 0;
+ }
+
+ return r;
+}
+
+static int dns_transaction_emit_tcp(DnsTransaction *t) {
_cleanup_close_ int fd = -1;
+ _cleanup_(dns_stream_unrefp) DnsStream *s = NULL;
+ union sockaddr_union sa;
int r;
+#if ENABLE_DNS_OVER_TLS
+ gnutls_session_t gs;
+#endif
assert(t);
@@ -544,13 +599,17 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
if (r < 0)
return r;
- fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, 53);
+ if (t->server->stream && (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) == t->server->stream->encrypted))
+ s = dns_stream_ref(t->server->stream);
+ else
+ fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) ? 853 : 53, &sa);
+
break;
case DNS_PROTOCOL_LLMNR:
/* When we already received a reply to this (but it was truncated), send to its sender address */
if (t->received)
- fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, NULL, t->received->sender_port);
+ fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, NULL, t->received->sender_port, &sa);
else {
union in_addr_union address;
int family = AF_UNSPEC;
@@ -567,7 +626,7 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
if (family != t->scope->family)
return -ESRCH;
- fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT);
+ fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT, &sa);
}
break;
@@ -576,28 +635,67 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
return -EAFNOSUPPORT;
}
- if (fd < 0)
- return fd;
+ if (!s) {
+ if (fd < 0)
+ return fd;
- r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
- if (r < 0)
- return r;
- fd = -1;
+ r = dns_stream_new(t->scope->manager, &s, t->scope->protocol, fd, &sa);
+ if (r < 0)
+ return r;
+
+ fd = -1;
+
+ if (t->server) {
+ dns_stream_unref(t->server->stream);
+ t->server->stream = dns_stream_ref(s);
+ s->server = dns_server_ref(t->server);
+ }
+
+#if ENABLE_DNS_OVER_TLS
+ if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) {
+ r = gnutls_init(&gs, GNUTLS_CLIENT | GNUTLS_ENABLE_FALSE_START | GNUTLS_NONBLOCK);
+ if (r < 0)
+ return r;
+
+ /* As DNS-over-TLS is a recent protocol, older TLS versions can be disabled */
+ r = gnutls_priority_set_direct(gs, "NORMAL:-VERS-ALL:+VERS-TLS1.2", NULL);
+ if (r < 0)
+ return r;
+
+ r = gnutls_credentials_set(gs, GNUTLS_CRD_CERTIFICATE, t->server->tls_cert_cred);
+ if (r < 0)
+ return r;
+
+ if (t->server && t->server->tls_session_data.size > 0)
+ gnutls_session_set_data(gs, t->server->tls_session_data.data, t->server->tls_session_data.size);
+
+ gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
+
+ r = dns_stream_connect_tls(s, gs);
+ if (r < 0)
+ return r;
+ }
+#endif
+
+ s->on_connection = on_stream_connection;
+ s->complete = on_stream_complete;
+ s->on_packet = dns_stream_on_packet;
+
+ /* The interface index is difficult to determine if we are
+ * connecting to the local host, hence fill this in right away
+ * instead of determining it from the socket */
+ s->ifindex = dns_scope_ifindex(t->scope);
+ }
+
+ t->stream = TAKE_PTR(s);
+ LIST_PREPEND(transactions_by_stream, t->stream->transactions, t);
r = dns_stream_write_packet(t->stream, t->sent);
if (r < 0) {
- t->stream = dns_stream_unref(t->stream);
+ dns_transaction_close_connection(t);
return r;
}
- t->stream->complete = on_stream_complete;
- t->stream->transaction = t;
-
- /* The interface index is difficult to determine if we are
- * connecting to the local host, hence fill this in right away
- * instead of determining it from the socket */
- t->stream->ifindex = dns_scope_ifindex(t->scope);
-
dns_transaction_reset_answer(t);
t->tried_stream = true;
@@ -691,7 +789,6 @@ static int dns_transaction_dnssec_ready(DnsTransaction *t) {
dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
return 0;
-
default:
log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(dt->state));
goto fail;
@@ -845,7 +942,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
* should hence not attempt to access the query or transaction
* after calling this function. */
- log_debug("Processing incoming packet on transaction %" PRIu16". (rcode=%s)", t->id, dns_rcode_to_string(DNS_PACKET_RCODE(p)));
+ log_debug("Processing incoming packet on transaction %" PRIu16" (rcode=%s).",
+ t->id, dns_rcode_to_string(DNS_PACKET_RCODE(p)));
switch (t->scope->protocol) {
@@ -944,7 +1042,17 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
}
/* Reduce this feature level by one and try again. */
- t->clamp_feature_level = t->current_feature_level - 1;
+ switch (t->current_feature_level) {
+ case DNS_SERVER_FEATURE_LEVEL_TLS_DO:
+ t->clamp_feature_level = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN;
+ break;
+ case DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN + 1:
+ /* Skip plain TLS when TLS is not supported */
+ t->clamp_feature_level = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN - 1;
+ break;
+ default:
+ t->clamp_feature_level = t->current_feature_level - 1;
+ }
log_debug("Server returned error %s, retrying transaction with reduced feature level %s.",
dns_rcode_to_string(DNS_PACKET_RCODE(p)),
@@ -986,7 +1094,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
log_debug("Reply truncated, retrying via TCP.");
/* Response was truncated, let's try again with good old TCP */
- r = dns_transaction_open_tcp(t);
+ r = dns_transaction_emit_tcp(t);
if (r == -ESRCH) {
/* No servers found? Damn! */
dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
@@ -1030,7 +1138,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
dns_server_packet_bad_opt(t->server, t->current_feature_level);
/* Report that we successfully received a packet */
- dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, ts - t->start_usec, p->size);
+ dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, p->size);
}
/* See if we know things we didn't know before that indicate we better restart the lookup immediately. */
@@ -1119,7 +1227,7 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
log_debug_errno(r, "Connection failure for DNS UDP packet: %m");
assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
- dns_server_packet_lost(t->server, IPPROTO_UDP, t->current_feature_level, usec - t->start_usec);
+ dns_server_packet_lost(t->server, IPPROTO_UDP, t->current_feature_level);
dns_transaction_retry(t, true);
return 0;
@@ -1160,7 +1268,7 @@ static int dns_transaction_emit_udp(DnsTransaction *t) {
if (r < 0)
return r;
- if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP)
+ if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP || DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level))
return -EAGAIN; /* Sorry, can't do UDP, try TCP! */
if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type))
@@ -1212,7 +1320,7 @@ static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdat
case DNS_PROTOCOL_DNS:
assert(t->server);
- dns_server_packet_lost(t->server, t->stream ? IPPROTO_TCP : IPPROTO_UDP, t->current_feature_level, usec - t->start_usec);
+ dns_server_packet_lost(t->server, t->stream ? IPPROTO_TCP : IPPROTO_UDP, t->current_feature_level);
break;
case DNS_PROTOCOL_LLMNR:
@@ -1238,7 +1346,6 @@ static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
assert(t);
assert(t->scope);
-
switch (t->scope->protocol) {
case DNS_PROTOCOL_DNS:
@@ -1249,8 +1356,7 @@ static usec_t transaction_get_resend_timeout(DnsTransaction *t) {
if (t->stream)
return TRANSACTION_TCP_TIMEOUT_USEC;
- assert(t->server);
- return t->server->resend_timeout;
+ return DNS_TIMEOUT_USEC;
case DNS_PROTOCOL_MDNS:
assert(t->n_attempts > 0);
@@ -1530,8 +1636,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
}
DNS_PACKET_HEADER(p)->nscount = htobe16(nscount);
- t->sent = p;
- p = NULL;
+ t->sent = TAKE_PTR(p);
return 0;
}
@@ -1559,8 +1664,7 @@ static int dns_transaction_make_packet(DnsTransaction *t) {
DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
DNS_PACKET_HEADER(p)->id = t->id;
- t->sent = p;
- p = NULL;
+ t->sent = TAKE_PTR(p);
return 0;
}
@@ -1645,7 +1749,7 @@ int dns_transaction_go(DnsTransaction *t) {
/* RFC 4795, Section 2.4. says reverse lookups shall
* always be made via TCP on LLMNR */
- r = dns_transaction_open_tcp(t);
+ r = dns_transaction_emit_tcp(t);
} else {
/* Try via UDP, and if that fails due to large size or lack of
* support try via TCP */
@@ -1653,9 +1757,9 @@ int dns_transaction_go(DnsTransaction *t) {
if (r == -EMSGSIZE)
log_debug("Sending query via TCP since it is too large.");
else if (r == -EAGAIN)
- log_debug("Sending query via TCP since server doesn't support UDP.");
+ log_debug("Sending query via TCP since UDP isn't supported.");
if (IN_SET(r, -EMSGSIZE, -EAGAIN))
- r = dns_transaction_open_tcp(t);
+ r = dns_transaction_emit_tcp(t);
}
if (r == -ESRCH) {
@@ -3079,8 +3183,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
}
dns_answer_unref(t->answer);
- t->answer = validated;
- validated = NULL;
+ t->answer = TAKE_PTR(validated);
/* At this point the answer only contains validated
* RRsets. Now, let's see if it actually answers the question
diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h
index 31dcd7627a..bdfcbc1acc 100644
--- a/src/resolve/resolved-dns-transaction.h
+++ b/src/resolve/resolved-dns-transaction.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct DnsTransaction DnsTransaction;
typedef enum DnsTransactionState DnsTransactionState;
typedef enum DnsTransactionSource DnsTransactionSource;
@@ -149,6 +130,7 @@ struct DnsTransaction {
unsigned block_gc;
LIST_FIELDS(DnsTransaction, transactions_by_scope);
+ LIST_FIELDS(DnsTransaction, transactions_by_stream);
};
int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key);
diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c
index c6e47ed0e9..533e438fae 100644
--- a/src/resolve/resolved-dns-trust-anchor.c
+++ b/src/resolve/resolved-dns-trust-anchor.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-messages.h"
@@ -255,18 +237,18 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u
}
if (strcaseeq(type, "DS")) {
- _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL, *digest = NULL;
+ _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL;
_cleanup_free_ void *dd = NULL;
uint16_t kt;
int a, dt;
size_t l;
- r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, &digest, NULL);
+ r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to parse DS parameters on line %s:%u: %m", path, line);
return -EINVAL;
}
- if (r != 4) {
+ if (r != 3) {
log_warning("Missing DS parameters on line %s:%u", path, line);
return -EINVAL;
}
@@ -287,9 +269,14 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u
return -EINVAL;
}
- r = unhexmem(digest, strlen(digest), &dd, &l);
+ if (isempty(p)) {
+ log_warning("Missing DS digest on line %s:%u", path, line);
+ return -EINVAL;
+ }
+
+ r = unhexmem(p, strlen(p), &dd, &l);
if (r < 0) {
- log_warning("Failed to parse DS digest %s on line %s:%u", digest, path, line);
+ log_warning("Failed to parse DS digest %s on line %s:%u", p, path, line);
return -EINVAL;
}
@@ -301,20 +288,19 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u
rr->ds.algorithm = a;
rr->ds.digest_type = dt;
rr->ds.digest_size = l;
- rr->ds.digest = dd;
- dd = NULL;
+ rr->ds.digest = TAKE_PTR(dd);
} else if (strcaseeq(type, "DNSKEY")) {
- _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL, *key = NULL;
+ _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL;
_cleanup_free_ void *k = NULL;
uint16_t f;
size_t l;
int a;
- r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, &key, NULL);
+ r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, NULL);
if (r < 0)
return log_warning_errno(r, "Failed to parse DNSKEY parameters on line %s:%u: %m", path, line);
- if (r != 4) {
+ if (r != 3) {
log_warning("Missing DNSKEY parameters on line %s:%u", path, line);
return -EINVAL;
}
@@ -342,9 +328,14 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u
return -EINVAL;
}
- r = unbase64mem(key, strlen(key), &k, &l);
+ if (isempty(p)) {
+ log_warning("Missing DNSKEY key on line %s:%u", path, line);
+ return -EINVAL;
+ }
+
+ r = unbase64mem(p, strlen(p), &k, &l);
if (r < 0)
- return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", key, path, line);
+ return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", p, path, line);
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, domain);
if (!rr)
@@ -354,19 +345,13 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u
rr->dnskey.protocol = 3;
rr->dnskey.algorithm = a;
rr->dnskey.key_size = l;
- rr->dnskey.key = k;
- k = NULL;
+ rr->dnskey.key = TAKE_PTR(k);
} else {
log_warning("RR type %s is not supported, ignoring line %s:%u.", type, path, line);
return -EINVAL;
}
- if (!isempty(p)) {
- log_warning("Trailing garbage on line %s:%u, ignoring line.", path, line);
- return -EINVAL;
- }
-
r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops);
if (r < 0)
return log_oom();
@@ -640,9 +625,10 @@ static int dns_trust_anchor_remove_revoked(DnsTrustAnchor *d, DnsResourceRecord
/* We found the key! Warn the user */
log_struct(LOG_WARNING,
"MESSAGE_ID=" SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED_STR,
- LOG_MESSAGE("DNSSEC Trust anchor %s has been revoked. Please update the trust anchor, or upgrade your operating system."), strna(dns_resource_record_to_string(rr)),
- "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr),
- NULL);
+ LOG_MESSAGE("DNSSEC trust anchor %s has been revoked.\n"
+ "Please update the trust anchor, or upgrade your operating system.",
+ strna(dns_resource_record_to_string(rr))),
+ "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr));
if (dns_answer_size(new_answer) <= 0) {
assert_se(hashmap_remove(d->positive_by_key, rr->key) == old_answer);
diff --git a/src/resolve/resolved-dns-trust-anchor.h b/src/resolve/resolved-dns-trust-anchor.h
index 94d620e657..df49777e26 100644
--- a/src/resolve/resolved-dns-trust-anchor.h
+++ b/src/resolve/resolved-dns-trust-anchor.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef struct DnsTrustAnchor DnsTrustAnchor;
#include "hashmap.h"
diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c
index dcb9702e57..c2d9f3d33d 100644
--- a/src/resolve/resolved-dns-zone.c
+++ b/src/resolve/resolved-dns-zone.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "dns-domain.h"
@@ -36,8 +18,7 @@ void dns_zone_item_probe_stop(DnsZoneItem *i) {
if (!i->probe_transaction)
return;
- t = i->probe_transaction;
- i->probe_transaction = NULL;
+ t = TAKE_PTR(i->probe_transaction);
set_remove(t->notify_zone_items, i);
set_remove(t->notify_zone_items_done, i);
@@ -488,13 +469,10 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **re
if (!ret_tentative && tentative)
goto return_empty;
- *ret_answer = answer;
- answer = NULL;
+ *ret_answer = TAKE_PTR(answer);
- if (ret_soa) {
- *ret_soa = soa;
- soa = NULL;
- }
+ if (ret_soa)
+ *ret_soa = TAKE_PTR(soa);
if (ret_tentative)
*ret_tentative = tentative;
diff --git a/src/resolve/resolved-dns-zone.h b/src/resolve/resolved-dns-zone.h
index c9c7440351..2719b2188a 100644
--- a/src/resolve/resolved-dns-zone.h
+++ b/src/resolve/resolved-dns-zone.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "hashmap.h"
typedef struct DnsZone {
diff --git a/src/resolve/resolved-dnssd-bus.c b/src/resolve/resolved-dnssd-bus.c
index c914e8f8d2..c2db31df0f 100644
--- a/src/resolve/resolved-dnssd-bus.c
+++ b/src/resolve/resolved-dnssd-bus.c
@@ -1,21 +1,3 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 Dmitry Rozhkov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-util.h"
@@ -139,8 +121,7 @@ int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char **
}
l[c] = NULL;
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/resolve/resolved-dnssd-bus.h b/src/resolve/resolved-dnssd-bus.h
index ab915c86f9..403cb00a53 100644
--- a/src/resolve/resolved-dnssd-bus.h
+++ b/src/resolve/resolved-dnssd-bus.h
@@ -1,23 +1,5 @@
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Dmitry Rozhkov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-bus.h"
diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c
index db589f4436..aa4bd74788 100644
--- a/src/resolve/resolved-dnssd.c
+++ b/src/resolve/resolved-dnssd.c
@@ -1,21 +1,3 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 Dmitry Rozhkov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "conf-files.h"
#include "conf-parser.h"
@@ -179,7 +161,7 @@ int dnssd_render_instance_name(DnssdService *s, char **ret_name) {
static const Specifier specifier_table[] = {
{ 'b', specifier_boot_id, NULL },
{ 'H', specifier_dnssd_host_name, NULL },
- { 'm', specifier_machine_id, NULL },
+ { 'm', specifier_machine_id, NULL },
{ 'v', specifier_kernel_release, NULL },
{}
};
@@ -198,8 +180,7 @@ int dnssd_render_instance_name(DnssdService *s, char **ret_name) {
return -EINVAL;
}
- *ret_name = name;
- name = NULL;
+ *ret_name = TAKE_PTR(name);
return 0;
}
@@ -319,8 +300,7 @@ int dnssd_txt_item_new_from_string(const char *key, const char *value, DnsTxtIte
}
i->length = length;
- *ret_item = i;
- i = NULL;
+ *ret_item = TAKE_PTR(i);
return 0;
}
@@ -345,8 +325,7 @@ int dnssd_txt_item_new_from_data(const char *key, const void *data, const size_t
}
i->length = length;
- *ret_item = i;
- i = NULL;
+ *ret_item = TAKE_PTR(i);
return 0;
}
diff --git a/src/resolve/resolved-dnssd.h b/src/resolve/resolved-dnssd.h
index fbc043d673..f49cfe2515 100644
--- a/src/resolve/resolved-dnssd.h
+++ b/src/resolve/resolved-dnssd.h
@@ -1,23 +1,5 @@
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Dmitry Rozhkov
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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"
diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c
index 769cfb78e7..507f68b47f 100644
--- a/src/resolve/resolved-etc-hosts.c
+++ b/src/resolve/resolved-etc-hosts.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "fd-util.h"
#include "fileio.h"
diff --git a/src/resolve/resolved-etc-hosts.h b/src/resolve/resolved-etc-hosts.h
index 6756f13b41..b8e04c393b 100644
--- a/src/resolve/resolved-etc-hosts.h
+++ b/src/resolve/resolved-etc-hosts.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "resolved-manager.h"
#include "resolved-dns-question.h"
#include "resolved-dns-answer.h"
diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf
index a5865ce6c2..648ca4d8a2 100644
--- a/src/resolve/resolved-gperf.gperf
+++ b/src/resolve/resolved-gperf.gperf
@@ -23,5 +23,6 @@ Resolve.Domains, config_parse_search_domains, 0,
Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support)
Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support)
Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode)
+Resolve.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Manager, dns_over_tls_mode)
Resolve.Cache, config_parse_bool, 0, offsetof(Manager, enable_cache)
Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode)
diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c
index 711dff0954..b1581740d8 100644
--- a/src/resolve/resolved-link-bus.c
+++ b/src/resolve/resolved-link-bus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-common-errors.h"
@@ -28,9 +10,10 @@
#include "resolved-resolv-conf.h"
#include "strv.h"
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_resolve_support, resolve_support, ResolveSupport);
+static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported);
+static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string);
-static int property_get_dnssec_mode(
+static int property_get_dns_over_tls_mode(
sd_bus *bus,
const char *path,
const char *interface,
@@ -44,7 +27,7 @@ static int property_get_dnssec_mode(
assert(reply);
assert(l);
- return sd_bus_message_append(reply, "s", dnssec_mode_to_string(link_get_dnssec_mode(l)));
+ return sd_bus_message_append(reply, "s", dns_over_tls_mode_to_string(link_get_dns_over_tls_mode(l)));
}
static int property_get_dns(
@@ -76,6 +59,25 @@ static int property_get_dns(
return sd_bus_message_close_container(reply);
}
+static int property_get_current_dns_server(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ DnsServer *s;
+
+ assert(reply);
+ assert(userdata);
+
+ s = *(DnsServer **) userdata;
+
+ return bus_dns_server_append(reply, s, false);
+}
+
static int property_get_domains(
sd_bus *bus,
const char *path,
@@ -159,23 +161,6 @@ static int property_get_ntas(
return sd_bus_message_close_container(reply);
}
-static int property_get_dnssec_supported(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Link *l = userdata;
-
- assert(reply);
- assert(l);
-
- return sd_bus_message_append(reply, "b", link_dnssec_supported(l));
-}
-
static int verify_unmanaged_link(Link *l, sd_bus_error *error) {
assert(l);
@@ -429,6 +414,38 @@ int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_err
return sd_bus_reply_method_return(message, NULL);
}
+int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Link *l = userdata;
+ const char *dns_over_tls;
+ DnsOverTlsMode mode;
+ int r;
+
+ assert(message);
+ assert(l);
+
+ r = verify_unmanaged_link(l, error);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(message, "s", &dns_over_tls);
+ if (r < 0)
+ return r;
+
+ if (isempty(dns_over_tls))
+ mode = _DNS_OVER_TLS_MODE_INVALID;
+ else {
+ mode = dns_over_tls_mode_from_string(dns_over_tls);
+ if (mode < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls);
+ }
+
+ link_set_dns_over_tls_mode(l, mode);
+
+ (void) link_save_user(l);
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Link *l = userdata;
const char *dnssec;
@@ -498,8 +515,7 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v
}
set_free_free(l->dnssec_negative_trust_anchors);
- l->dnssec_negative_trust_anchors = ns;
- ns = NULL;
+ l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
(void) link_save_user(l);
@@ -532,9 +548,11 @@ const sd_bus_vtable link_vtable[] = {
SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
+ SD_BUS_PROPERTY("CurrentDNSServer", "(iay)", property_get_current_dns_server, offsetof(Link, current_dns_server), 0),
SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
- SD_BUS_PROPERTY("LLMNR", "s", property_get_resolve_support, offsetof(Link, llmnr_support), 0),
- SD_BUS_PROPERTY("MulticastDNS", "s", property_get_resolve_support, offsetof(Link, mdns_support), 0),
+ SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Link, llmnr_support), 0),
+ SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Link, mdns_support), 0),
+ SD_BUS_PROPERTY("DNSOverTLS", "s", property_get_dns_over_tls_mode, 0, 0),
SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, 0, 0),
SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0),
SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported, 0, 0),
@@ -543,6 +561,7 @@ const sd_bus_vtable link_vtable[] = {
SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, 0),
SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0),
SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0),
+ SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, 0),
SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0),
SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, 0),
SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, 0),
@@ -623,8 +642,7 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
}
l[c] = NULL;
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/resolve/resolved-link-bus.h b/src/resolve/resolved-link-bus.h
index deed6fe66d..6b8092fdb4 100644
--- a/src/resolve/resolved-link-bus.h
+++ b/src/resolve/resolved-link-bus.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "sd-bus.h"
#include "resolved-link.h"
@@ -34,6 +15,7 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_
int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error);
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index e3e50eca53..ff2be12415 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
#include <stdio_ext.h>
@@ -54,6 +36,7 @@ int link_new(Manager *m, Link **ret, int ifindex) {
l->llmnr_support = RESOLVE_SUPPORT_YES;
l->mdns_support = RESOLVE_SUPPORT_NO;
l->dnssec_mode = _DNSSEC_MODE_INVALID;
+ l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
l->operstate = IF_OPER_UNKNOWN;
if (asprintf(&l->state_file, "/run/systemd/resolve/netif/%i", ifindex) < 0)
@@ -78,6 +61,7 @@ void link_flush_settings(Link *l) {
l->llmnr_support = RESOLVE_SUPPORT_YES;
l->mdns_support = RESOLVE_SUPPORT_NO;
l->dnssec_mode = _DNSSEC_MODE_INVALID;
+ l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
dns_server_unlink_all(l->dns_servers);
dns_search_domain_unlink_all(l->search_domains);
@@ -128,6 +112,11 @@ void link_allocate_scopes(Link *l) {
dns_server_reset_features_all(l->manager->fallback_dns_servers);
dns_server_reset_features_all(l->manager->dns_servers);
+
+ /* Also, flush the global unicast scope, to deal with split horizon setups, where talking through one
+ * interface reveals different DNS zones than through others. */
+ if (l->manager->unicast_scope)
+ dns_cache_flush(&l->manager->unicast_scope->cache);
}
/* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't
@@ -360,6 +349,46 @@ clear:
return r;
}
+void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode) {
+
+ assert(l);
+
+#if ! ENABLE_DNS_OVER_TLS
+ if (mode != DNS_OVER_TLS_NO)
+ log_warning("DNS-over-TLS option for the link cannot be set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
+ return;
+#endif
+
+ l->dns_over_tls_mode = mode;
+}
+
+static int link_update_dns_over_tls_mode(Link *l) {
+ _cleanup_free_ char *b = NULL;
+ int r;
+
+ assert(l);
+
+ r = sd_network_link_get_dns_over_tls(l->ifindex, &b);
+ if (r == -ENODATA) {
+ r = 0;
+ goto clear;
+ }
+ if (r < 0)
+ goto clear;
+
+ l->dns_over_tls_mode = dns_over_tls_mode_from_string(b);
+ if (l->dns_over_tls_mode < 0) {
+ r = -EINVAL;
+ goto clear;
+ }
+
+ return 0;
+
+clear:
+ l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
+ return r;
+}
+
void link_set_dnssec_mode(Link *l, DnssecMode mode) {
assert(l);
@@ -440,8 +469,7 @@ static int link_update_dnssec_negative_trust_anchors(Link *l) {
return r;
set_free_free(l->dnssec_negative_trust_anchors);
- l->dnssec_negative_trust_anchors = ns;
- ns = NULL;
+ l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
return 0;
@@ -568,6 +596,10 @@ static void link_read_settings(Link *l) {
if (r < 0)
log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
+ r = link_update_dns_over_tls_mode(l);
+ if (r < 0)
+ log_warning_errno(r, "Failed to read DNS-over-TLS mode for interface %s, ignoring: %m", l->name);
+
r = link_update_dnssec_mode(l);
if (r < 0)
log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
@@ -701,6 +733,15 @@ void link_next_dns_server(Link *l) {
link_set_dns_server(l, l->dns_servers);
}
+DnsOverTlsMode link_get_dns_over_tls_mode(Link *l) {
+ assert(l);
+
+ if (l->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
+ return l->dns_over_tls_mode;
+
+ return manager_get_dns_over_tls_mode(l->manager);
+}
+
DnssecMode link_get_dnssec_mode(Link *l) {
assert(l);
@@ -1216,7 +1257,7 @@ int link_load_user(Link *l) {
if (l->is_managed)
return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
- r = parse_env_file(l->state_file, NEWLINE,
+ r = parse_env_file(NULL, l->state_file, NEWLINE,
"LLMNR", &llmnr,
"MDNS", &mdns,
"DNSSEC", &dnssec,
@@ -1293,8 +1334,7 @@ int link_load_user(Link *l) {
if (r < 0)
goto fail;
- l->dnssec_negative_trust_anchors = ns;
- ns = NULL;
+ l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
}
return 0;
diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h
index 261e34bfe2..063d3f35c3 100644
--- a/src/resolve/resolved-link.h
+++ b/src/resolve/resolved-link.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <net/if.h>
#include "in-addr-util.h"
@@ -72,6 +53,7 @@ struct Link {
ResolveSupport llmnr_support;
ResolveSupport mdns_support;
+ DnsOverTlsMode dns_over_tls_mode;
DnssecMode dnssec_mode;
Set *dnssec_negative_trust_anchors;
@@ -103,6 +85,7 @@ void link_add_rrs(Link *l, bool force_remove);
void link_flush_settings(Link *l);
void link_set_dnssec_mode(Link *l, DnssecMode mode);
+void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode);
void link_allocate_scopes(Link *l);
DnsServer* link_set_dns_server(Link *l, DnsServer *s);
@@ -112,6 +95,8 @@ void link_next_dns_server(Link *l);
DnssecMode link_get_dnssec_mode(Link *l);
bool link_dnssec_supported(Link *l);
+DnsOverTlsMode link_get_dns_over_tls_mode(Link *l);
+
int link_save_user(Link *l);
int link_load_user(Link *l);
void link_remove_user(Link *l);
diff --git a/src/resolve/resolved-llmnr.c b/src/resolve/resolved-llmnr.c
index 59499c9c0b..2f2a1a15ec 100644
--- a/src/resolve/resolved-llmnr.c
+++ b/src/resolve/resolved-llmnr.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
#include <netinet/in.h>
#include <resolv.h>
@@ -358,7 +340,7 @@ static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *u
return -errno;
}
- r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
+ r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd, NULL);
if (r < 0) {
safe_close(cfd);
return r;
diff --git a/src/resolve/resolved-llmnr.h b/src/resolve/resolved-llmnr.h
index 7670380c51..a3b12cf38c 100644
--- a/src/resolve/resolved-llmnr.h
+++ b/src/resolve/resolved-llmnr.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "resolved-manager.h"
#define LLMNR_PORT 5355
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index daa8292e8b..9155ce5c2e 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
#include <netinet/in.h>
#include <poll.h>
@@ -396,11 +378,8 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
if (r < 0)
return log_error_errno(r, "Failed to determine mDNS hostname: %m");
- *llmnr_hostname = n;
- n = NULL;
-
- *full_hostname = h;
- h = NULL;
+ *llmnr_hostname = TAKE_PTR(n);
+ *full_hostname = TAKE_PTR(h);
return 0;
}
@@ -445,11 +424,8 @@ static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname,
if (!h)
return log_oom();
- *llmnr_hostname = n;
- n = NULL;
-
- *mdns_hostname = m;
- m = NULL;
+ *llmnr_hostname = TAKE_PTR(n);
+ *mdns_hostname = TAKE_PTR(m);
*full_hostname = h;
@@ -599,6 +575,7 @@ int manager_new(Manager **ret) {
m->llmnr_support = RESOLVE_SUPPORT_YES;
m->mdns_support = RESOLVE_SUPPORT_YES;
m->dnssec_mode = DEFAULT_DNSSEC_MODE;
+ m->dns_over_tls_mode = DEFAULT_DNS_OVER_TLS_MODE;
m->enable_cache = true;
m->dns_stub_listener_mode = DNS_STUB_LISTENER_UDP;
m->read_resolv_conf = true;
@@ -652,8 +629,7 @@ int manager_new(Manager **ret) {
manager_cleanup_saved_user(m);
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
@@ -708,7 +684,6 @@ Manager *manager_free(Manager *m) {
manager_dns_stub_stop(m);
sd_bus_slot_unref(m->prepare_for_sleep_slot);
- sd_event_source_unref(m->bus_retry_event_source);
sd_bus_unref(m->bus);
sd_event_source_unref(m->sigusr1_event_source);
@@ -861,8 +836,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
}
- *ret = p;
- p = NULL;
+ *ret = TAKE_PTR(p);
return 1;
}
@@ -1406,6 +1380,15 @@ bool manager_dnssec_supported(Manager *m) {
return true;
}
+DnsOverTlsMode manager_get_dns_over_tls_mode(Manager *m) {
+ assert(m);
+
+ if (m->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
+ return m->dns_over_tls_mode;
+
+ return DNS_OVER_TLS_NO;
+}
+
void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key) {
assert(verdict >= 0);
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index 5c1a6670ef..d94b2888ab 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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-event.h"
#include "sd-netlink.h"
@@ -48,6 +30,7 @@ struct Manager {
ResolveSupport llmnr_support;
ResolveSupport mdns_support;
DnssecMode dnssec_mode;
+ DnsOverTlsMode dns_over_tls_mode;
bool enable_cache;
DnsStubListenerMode dns_stub_listener_mode;
@@ -110,7 +93,6 @@ struct Manager {
/* dbus */
sd_bus *bus;
- sd_event_source *bus_retry_event_source;
/* The hostname we publish on LLMNR and mDNS */
char *full_hostname;
@@ -186,6 +168,8 @@ int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_
DnssecMode manager_get_dnssec_mode(Manager *m);
bool manager_dnssec_supported(Manager *m);
+DnsOverTlsMode manager_get_dns_over_tls_mode(Manager *m);
+
void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key);
bool manager_routable(Manager *m, int family);
diff --git a/src/resolve/resolved-mdns.c b/src/resolve/resolved-mdns.c
index 38e2c54227..71a30ae8f8 100644
--- a/src/resolve/resolved-mdns.c
+++ b/src/resolve/resolved-mdns.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
#include <resolv.h>
#include <netinet/in.h>
@@ -146,7 +128,7 @@ static int mdns_packet_extract_matching_rrs(DnsPacket *p, DnsResourceKey *key, D
assert(ret_rrs);
assert_return(DNS_PACKET_NSCOUNT(p) > 0, -EINVAL);
- for (unsigned i = DNS_PACKET_ANCOUNT(p); i < (DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)); i++) {
+ for (size_t i = DNS_PACKET_ANCOUNT(p); i < (DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)); i++) {
r = dns_resource_key_match_rr(key, p->answer->items[i].rr, NULL);
if (r < 0)
return r;
@@ -161,7 +143,7 @@ static int mdns_packet_extract_matching_rrs(DnsPacket *p, DnsResourceKey *key, D
if (!list)
return -ENOMEM;
- for (unsigned i = DNS_PACKET_ANCOUNT(p); i < (DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)); i++) {
+ for (size_t i = DNS_PACKET_ANCOUNT(p); i < (DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)); i++) {
r = dns_resource_key_match_rr(key, p->answer->items[i].rr, NULL);
if (r < 0)
return r;
@@ -171,8 +153,7 @@ static int mdns_packet_extract_matching_rrs(DnsPacket *p, DnsResourceKey *key, D
assert(n == size);
qsort_safe(list, size, sizeof(DnsResourceRecord*), mdns_rr_compare);
- *ret_rrs = list;
- list = NULL;
+ *ret_rrs = TAKE_PTR(list);
return size;
}
@@ -180,8 +161,7 @@ static int mdns_packet_extract_matching_rrs(DnsPacket *p, DnsResourceKey *key, D
static int mdns_do_tiebreak(DnsResourceKey *key, DnsAnswer *answer, DnsPacket *p) {
_cleanup_free_ DnsResourceRecord **our = NULL, **remote = NULL;
DnsResourceRecord *rr;
- unsigned i = 0;
- unsigned size;
+ size_t i = 0, size;
int r;
size = dns_answer_size(answer);
@@ -266,7 +246,7 @@ static int mdns_scope_process_query(DnsScope *s, DnsPacket *p) {
if (r < 0)
return log_debug_errno(r, "Failed to build reply packet: %m");
- if (!ratelimit_test(&s->ratelimit))
+ if (!ratelimit_below(&s->ratelimit))
return 0;
r = dns_scope_emit_udp(s, -1, reply);
diff --git a/src/resolve/resolved-mdns.h b/src/resolve/resolved-mdns.h
index af9f7a9aa6..d2bce6fcd9 100644
--- a/src/resolve/resolved-mdns.h
+++ b/src/resolve/resolved-mdns.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "resolved-manager.h"
diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c
index c828e9201f..5a022507c9 100644
--- a/src/resolve/resolved-resolv-conf.c
+++ b/src/resolve/resolved-resolv-conf.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
#include <resolv.h>
#include <stdio_ext.h>
@@ -192,7 +174,7 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
assert(count);
if (!dns_server_string(s)) {
- log_warning("Our of memory, or invalid DNS address. Ignoring server.");
+ log_warning("Out of memory, or invalid DNS address. Ignoring server.");
return;
}
@@ -281,7 +263,7 @@ static int write_stub_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet
"# internal DNS stub resolver of systemd-resolved. This file lists all\n"
"# configured search domains.\n"
"#\n"
- "# Run \"systemd-resolve --status\" to see details about the uplink DNS servers\n"
+ "# Run \"resolvectl status\" to see details about the uplink DNS servers\n"
"# currently in use.\n"
"#\n"
"# Third party programs must not access this file directly, but only through the\n"
diff --git a/src/resolve/resolved-resolv-conf.h b/src/resolve/resolved-resolv-conf.h
index ef34f8e09e..105ae4cae8 100644
--- a/src/resolve/resolved-resolv-conf.h
+++ b/src/resolve/resolved-resolv-conf.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "resolved-manager.h"
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index a4cda0b5ef..c01e53e9da 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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"
#include "sd-event.h"
@@ -62,7 +44,7 @@ int main(int argc, char *argv[]) {
}
/* Always create the directory where resolv.conf will live */
- r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, false);
+ r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, MKDIR_WARN_MODE);
if (r < 0) {
log_error_errno(r, "Could not create runtime directory: %m");
goto finish;
diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in
index e6b20620e2..2528340f74 100644
--- a/src/resolve/resolved.conf.in
+++ b/src/resolve/resolved.conf.in
@@ -18,5 +18,6 @@
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=@DEFAULT_DNSSEC_MODE@
+#DNSOverTLS=@DEFAULT_DNS_OVER_TLS_MODE@
#Cache=yes
#DNSStubListener=udp
diff --git a/src/resolve/test-dns-packet.c b/src/resolve/test-dns-packet.c
index c1f118fecc..905f000dc2 100644
--- a/src/resolve/test-dns-packet.c
+++ b/src/resolve/test-dns-packet.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
#include <glob.h>
diff --git a/src/resolve/test-dnssec-complex.c b/src/resolve/test-dnssec-complex.c
index 514f72eeeb..ccd62a14d1 100644
--- a/src/resolve/test-dnssec-complex.c
+++ b/src/resolve/test-dnssec-complex.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/ip.h>
@@ -159,9 +141,14 @@ int main(int argc, char* argv[]) {
test_rr_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
test_hostname_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
+ /* Missing DS for DNSKEY */
+ test_rr_lookup(bus, "www.dnssec-bogus.sg", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
+ test_hostname_lookup(bus, "www.dnssec-bogus.sg", AF_INET, BUS_ERROR_DNSSEC_FAILED);
+
/* NXDOMAIN in NSEC domain */
test_rr_lookup(bus, "hhh.nasa.gov", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
test_hostname_lookup(bus, "hhh.nasa.gov", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
+ test_rr_lookup(bus, "_pgpkey-https._tcp.hkps.pool.sks-keyservers.net", DNS_TYPE_SRV, _BUS_ERROR_DNS "NXDOMAIN");
/* wildcard, NSEC zone */
test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_A, NULL);
diff --git a/src/resolve/test-dnssec.c b/src/resolve/test-dnssec.c
index ebabfba96d..568d8e0790 100644
--- a/src/resolve/test-dnssec.c
+++ b/src/resolve/test-dnssec.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#if HAVE_GCRYPT
diff --git a/src/resolve/test-resolve-tables.c b/src/resolve/test-resolve-tables.c
index 808ec76a41..842d42b311 100644
--- a/src/resolve/test-resolve-tables.c
+++ b/src/resolve/test-resolve-tables.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "dns-type.h"
#include "test-tables.h"
diff --git a/src/resolve/test-resolved-packet.c b/src/resolve/test-resolved-packet.c
index af5bec1391..22ae26ce12 100644
--- a/src/resolve/test-resolved-packet.c
+++ b/src/resolve/test-resolved-packet.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "log.h"
#include "resolved-dns-packet.h"
diff --git a/src/rfkill/rfkill.c b/src/rfkill/rfkill.c
index ff951450b5..7f3e055b1a 100644
--- a/src/rfkill/rfkill.c
+++ b/src/rfkill/rfkill.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/rfkill.h>
#include <poll.h>
@@ -49,12 +31,12 @@ typedef struct write_queue_item {
int state;
} write_queue_item;
-static void write_queue_item_free(struct write_queue_item *item)
-{
- assert(item);
+static struct write_queue_item* write_queue_item_free(struct write_queue_item *item) {
+ if (!item)
+ return NULL;
free(item->file);
- free(item);
+ return mfree(item);
}
static const char* const rfkill_type_table[NUM_RFKILL_TYPES] = {
@@ -89,8 +71,8 @@ static int find_device(
device = udev_device_new_from_subsystem_sysname(udev, "rfkill", sysname);
if (!device)
- return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
- "Failed to open device %s: %m", sysname);
+ return log_full_errno(IN_SET(errno, ENOENT, ENXIO, ENODEV) ? LOG_DEBUG : LOG_ERR, errno,
+ "Failed to open device '%s': %m", sysname);
name = udev_device_get_sysattr_value(device, "name");
if (!name) {
@@ -110,7 +92,7 @@ static int wait_for_initialized(
struct udev_device *device,
struct udev_device **ret) {
- _cleanup_udev_monitor_unref_ struct udev_monitor *monitor = NULL;
+ _cleanup_(udev_monitor_unrefp) struct udev_monitor *monitor = NULL;
struct udev_device *d;
const char *sysname;
int watch_fd, r;
@@ -148,8 +130,8 @@ static int wait_for_initialized(
/* Check again, maybe things changed */
d = udev_device_new_from_subsystem_sysname(udev, "rfkill", sysname);
if (!d)
- return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
- "Failed to open device %s: %m", sysname);
+ return log_full_errno(IN_SET(errno, ENOENT, ENXIO, ENODEV) ? LOG_DEBUG : LOG_ERR, errno,
+ "Failed to open device '%s': %m", sysname);
if (udev_device_get_is_initialized(d) != 0) {
*ret = d;
@@ -157,7 +139,7 @@ static int wait_for_initialized(
}
for (;;) {
- _cleanup_udev_device_unref_ struct udev_device *t = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *t = NULL;
r = fd_wait_for_event(watch_fd, POLLIN, EXIT_USEC);
if (r == -EINTR)
@@ -185,8 +167,8 @@ static int determine_state_file(
const struct rfkill_event *event,
char **ret) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
const char *path_id, *type;
char *state_file;
int r;
@@ -313,16 +295,16 @@ static int save_state_queue(
r = determine_state_file(udev, event, &state_file);
if (r < 0)
return r;
+
save_state_queue_remove(write_queue, event->idx, state_file);
item = new0(struct write_queue_item, 1);
if (!item)
return -ENOMEM;
- item->file = state_file;
+ item->file = TAKE_PTR(state_file);
item->rfkill_idx = event->idx;
item->state = event->soft;
- state_file = NULL;
LIST_APPEND(queue, *write_queue, item);
@@ -376,7 +358,7 @@ static int save_state_write(struct write_queue_item **write_queue) {
int main(int argc, char *argv[]) {
LIST_HEAD(write_queue_item, write_queue);
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
_cleanup_close_ int rfkill_fd = -1;
bool ready = false;
int r, n;
diff --git a/src/run/run.c b/src/run/run.c
index a30501169c..2910fcb272 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
#include <stdio.h>
@@ -520,7 +502,7 @@ static int transient_cgroup_set_properties(sd_bus_message *m) {
if (!isempty(arg_slice)) {
_cleanup_free_ char *slice = NULL;
- r = unit_name_mangle_with_suffix(arg_slice, UNIT_NAME_NOGLOB, ".slice", &slice);
+ r = unit_name_mangle_with_suffix(arg_slice, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, ".slice", &slice);
if (r < 0)
return log_error_errno(r, "Failed to mangle name '%s': %m", arg_slice);
@@ -875,7 +857,9 @@ static int run_context_update(RunContext *c, const char *path) {
"org.freedesktop.systemd1",
path,
map,
+ BUS_MAP_STRDUP,
&error,
+ NULL,
c);
if (r < 0) {
sd_event_exit(c->event, EXIT_FAILURE);
@@ -928,7 +912,7 @@ static int start_transient_service(
if (arg_stdio == ARG_STDIO_PTY) {
if (arg_transport == BUS_TRANSPORT_LOCAL) {
- master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
+ master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (master < 0)
return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
@@ -983,7 +967,7 @@ static int start_transient_service(
}
if (arg_unit) {
- r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
+ r = unit_name_mangle_with_suffix(arg_unit, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, ".service", &service);
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
} else {
@@ -1186,7 +1170,7 @@ static int start_transient_scope(
return log_oom();
if (arg_unit) {
- r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".scope", &scope);
+ r = unit_name_mangle_with_suffix(arg_unit, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, ".scope", &scope);
if (r < 0)
return log_error_errno(r, "Failed to mangle scope name: %m");
} else {
@@ -1357,11 +1341,11 @@ static int start_transient_trigger(
break;
default:
- r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service);
+ r = unit_name_mangle_with_suffix(arg_unit, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, ".service", &service);
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
- r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, suffix, &trigger);
+ r = unit_name_mangle_with_suffix(arg_unit, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, suffix, &trigger);
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index 889a971d88..1eaf653103 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011,2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdbool.h>
@@ -217,10 +199,8 @@ int acl_search_groups(const char *path, char ***ret_groups) {
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
}
- if (ret_groups) {
- *ret_groups = g;
- g = NULL;
- }
+ if (ret_groups)
+ *ret_groups = TAKE_PTR(g);
return ret;
}
@@ -287,9 +267,8 @@ int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want
}
}
- *acl_access = a_acl;
- *acl_default = d_acl;
- a_acl = d_acl = NULL;
+ *acl_access = TAKE_PTR(a_acl);
+ *acl_default = TAKE_PTR(d_acl);
return 0;
}
@@ -393,8 +372,8 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
if (r < 0)
return -errno;
- *acl = old;
- old = NULL;
+ *acl = TAKE_PTR(old);
+
return 0;
}
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
index 6b581cbc42..10b2a3d9f0 100644
--- a/src/shared/acl-util.h
+++ b/src/shared/acl-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#if HAVE_ACL
#include <acl/libacl.h>
diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c
index 1a640f4f1b..d565ebd43e 100644
--- a/src/shared/acpi-fpdt.c
+++ b/src/shared/acpi-fpdt.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 <errno.h>
#include <fcntl.h>
diff --git a/src/shared/acpi-fpdt.h b/src/shared/acpi-fpdt.h
index 4521a1e686..47bfefc5a0 100644
--- a/src/shared/acpi-fpdt.h
+++ b/src/shared/acpi-fpdt.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#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>
diff --git a/src/shared/apparmor-util.c b/src/shared/apparmor-util.c
index e9c4081892..c4a4b04d22 100644
--- a/src/shared/apparmor-util.c
+++ b/src/shared/apparmor-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
diff --git a/src/shared/apparmor-util.h b/src/shared/apparmor-util.h
index 33ebd4d612..7fbaf90dcc 100644
--- a/src/shared/apparmor-util.h
+++ b/src/shared/apparmor-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
bool mac_apparmor_use(void);
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index 4fa9188957..682dc754fc 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -730,8 +712,7 @@ int ask_password_agent(
if (keyname)
(void) add_to_keyring_and_log(keyname, flags, l);
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
r = 0;
finish:
diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h
index 4b2eb3fe92..93ca8bff52 100644
--- a/src/shared/ask-password-api.h
+++ b/src/shared/ask-password-api.h
@@ -1,37 +1,18 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "time-util.h"
typedef enum AskPasswordFlags {
- ASK_PASSWORD_ACCEPT_CACHED = 1U << 0,
- ASK_PASSWORD_PUSH_CACHE = 1U << 1,
- ASK_PASSWORD_ECHO = 1U << 2, /* show the password literally while reading, instead of "*" */
- ASK_PASSWORD_SILENT = 1U << 3, /* do no show any password at all while reading */
- ASK_PASSWORD_NO_TTY = 1U << 4,
- ASK_PASSWORD_NO_AGENT = 1U << 5,
- ASK_PASSWORD_CONSOLE_COLOR = 1U << 6, /* Use color if /dev/console points to a console that supports color */
+ ASK_PASSWORD_ACCEPT_CACHED = 1 << 0,
+ ASK_PASSWORD_PUSH_CACHE = 1 << 1,
+ ASK_PASSWORD_ECHO = 1 << 2, /* show the password literally while reading, instead of "*" */
+ ASK_PASSWORD_SILENT = 1 << 3, /* do no show any password at all while reading */
+ ASK_PASSWORD_NO_TTY = 1 << 4,
+ ASK_PASSWORD_NO_AGENT = 1 << 5,
+ ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */
} AskPasswordFlags;
int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char **ret);
diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c
index 3c25aa534c..89d7a7d59b 100644
--- a/src/shared/base-filesystem.c
+++ b/src/shared/base-filesystem.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <errno.h>
#include <fcntl.h>
@@ -63,8 +45,8 @@ static const BaseFilesystem table[] = {
int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
_cleanup_close_ int fd = -1;
- unsigned i;
int r = 0;
+ size_t i;
fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
if (fd < 0)
diff --git a/src/shared/base-filesystem.h b/src/shared/base-filesystem.h
index 5d134b4eb9..d1d4eaa662 100644
--- a/src/shared/base-filesystem.h
+++ b/src/shared/base-filesystem.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Kay Sievers
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/types.h>
diff --git a/src/shared/boot-timestamps.c b/src/shared/boot-timestamps.c
index 543e01a364..bcbb86d1b1 100644
--- a/src/shared/boot-timestamps.c
+++ b/src/shared/boot-timestamps.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 "acpi-fpdt.h"
#include "boot-timestamps.h"
diff --git a/src/shared/boot-timestamps.h b/src/shared/boot-timestamps.h
index 8c67d302b4..c719dd3602 100644
--- a/src/shared/boot-timestamps.h
+++ b/src/shared/boot-timestamps.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#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>
diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c
index 0e3e17a776..47a7dbafbd 100644
--- a/src/shared/bootspec.c
+++ b/src/shared/bootspec.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
#include <linux/magic.h>
@@ -138,13 +121,15 @@ int boot_entry_load(const char *path, BootEntry *entry) {
}
void boot_config_free(BootConfig *config) {
- unsigned i;
+ size_t i;
assert(config);
free(config->default_pattern);
free(config->timeout);
free(config->editor);
+ free(config->auto_entries);
+ free(config->auto_firmware);
free(config->entry_oneshot);
free(config->entry_default);
@@ -200,6 +185,12 @@ int boot_loader_read_conf(const char *path, BootConfig *config) {
r = free_and_strdup(&config->timeout, p);
else if (streq(field, "editor"))
r = free_and_strdup(&config->editor, p);
+ else if (streq(field, "auto-entries"))
+ r = free_and_strdup(&config->auto_entries, p);
+ else if (streq(field, "auto-firmware"))
+ r = free_and_strdup(&config->auto_firmware, p);
+ else if (streq(field, "console-mode"))
+ r = free_and_strdup(&config->console_mode, p);
else {
log_notice("%s:%u: Unknown line \"%s\"", path, line, field);
continue;
@@ -252,7 +243,7 @@ int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_en
}
static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) {
- unsigned i, j;
+ size_t i, j;
bool non_unique = false;
assert(entries || n_entries == 0);
@@ -272,7 +263,7 @@ static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) {
static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
char *s;
- unsigned i;
+ size_t i;
int r;
bool arr[n_entries];
@@ -402,7 +393,7 @@ static int verify_esp(
uint64_t *ret_psize,
sd_id128_t *ret_uuid) {
#if HAVE_BLKID
- _cleanup_blkid_free_probe_ blkid_probe b = NULL;
+ _cleanup_(blkid_free_probep) blkid_probe b = NULL;
char t[DEV_NUM_PATH_MAX];
const char *v;
#endif
diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h
index d9c641bf08..f47c073a46 100644
--- a/src/shared/bootspec.h
+++ b/src/shared/bootspec.h
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
@@ -40,6 +23,9 @@ typedef struct BootConfig {
char *default_pattern;
char *timeout;
char *editor;
+ char *auto_entries;
+ char *auto_firmware;
+ char *console_mode;
char *entry_oneshot;
char *entry_default;
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index e58d318c76..3238b442c0 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "bus-internal.h"
@@ -91,8 +73,7 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
return bus_log_create_error(r); \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#define DEFINE_BUS_APPEND_PARSE(bus_type, parse_func) \
static int bus_append_##parse_func( \
@@ -113,8 +94,7 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
return bus_log_create_error(r); \
\
return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
DEFINE_BUS_APPEND_PARSE("b", parse_boolean);
DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string);
@@ -124,7 +104,7 @@ DEFINE_BUS_APPEND_PARSE("i", log_level_from_string);
DEFINE_BUS_APPEND_PARSE("i", parse_errno);
DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string);
DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string);
-DEFINE_BUS_APPEND_PARSE("i", signal_from_string_try_harder);
+DEFINE_BUS_APPEND_PARSE("i", signal_from_string);
DEFINE_BUS_APPEND_PARSE("i", socket_protocol_from_name);
DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, ioprio_parse_priority);
DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, parse_nice);
@@ -462,7 +442,6 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
return bus_append_safe_atou64(m, field, eq);
return bus_append_parse_size(m, field, eq, 1024);
-
}
if (streq(field, "CPUQuota")) {
@@ -700,7 +679,8 @@ static int bus_append_automount_property(sd_bus_message *m, const char *field, c
}
static int bus_append_execute_property(sd_bus_message *m, const char *field, const char *eq) {
- int r, rl;
+ const char *suffix;
+ int r;
if (STR_IN_SET(field,
"User", "Group",
@@ -714,7 +694,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
if (STR_IN_SET(field,
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
- "NoNewPrivileges", "SyslogLevelPrefix",
+ "PrivateMounts", "NoNewPrivileges", "SyslogLevelPrefix",
"MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC",
"ProtectKernelTunables", "ProtectKernelModules", "ProtectControlGroups",
"MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality"))
@@ -879,25 +859,29 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
return bus_append_byte_array(m, field, decoded, sz);
}
- rl = rlimit_from_string(field);
- if (rl >= 0) {
- const char *sn;
- struct rlimit l;
+ if ((suffix = startswith(field, "Limit"))) {
+ int rl;
- r = rlimit_parse(rl, eq, &l);
- if (r < 0)
- return log_error_errno(r, "Failed to parse resource limit: %s", eq);
+ rl = rlimit_from_string(suffix);
+ if (rl >= 0) {
+ const char *sn;
+ struct rlimit l;
- r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max);
- if (r < 0)
- return bus_log_create_error(r);
+ r = rlimit_parse(rl, eq, &l);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse resource limit: %s", eq);
- sn = strjoina(field, "Soft");
- r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur);
- if (r < 0)
- return bus_log_create_error(r);
+ r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max);
+ if (r < 0)
+ return bus_log_create_error(r);
- return 1;
+ sn = strjoina(field, "Soft");
+ r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 1;
+ }
}
if (STR_IN_SET(field, "AppArmorProfile", "SmackProcessLabel")) {
@@ -982,7 +966,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
if (r < 0)
return bus_log_create_error(r);
- for (p = eq;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
@@ -1019,12 +1003,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
if (streq(field, "RestrictNamespaces")) {
bool invert = false;
- unsigned long flags = 0;
-
- if (eq[0] == '~') {
- invert = true;
- eq++;
- }
+ unsigned long flags;
r = parse_boolean(eq);
if (r > 0)
@@ -1032,7 +1011,12 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
else if (r == 0)
flags = NAMESPACE_FLAGS_ALL;
else {
- r = namespace_flag_from_string_many(eq, &flags);
+ if (eq[0] == '~') {
+ invert = true;
+ eq++;
+ }
+
+ r = namespace_flags_from_string(eq, &flags);
if (r < 0)
return log_error_errno(r, "Failed to parse %s value %s.", field, eq);
}
@@ -1114,7 +1098,6 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
} else
d = s;
-
r = sd_bus_message_append(m, "(ssbt)", s, d, ignore_enoent, flags);
if (r < 0)
return bus_log_create_error(r);
@@ -1168,8 +1151,10 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return log_error_errno(r, "Failed to parse argument: %m");
- if (r == 0)
- return log_error("Failed to parse argument: %m");
+ if (r == 0) {
+ log_error("Failed to parse argument: %s", p);
+ return -EINVAL;
+ }
r = sd_bus_message_append(m, "(ss)", path, w);
if (r < 0)
@@ -1206,7 +1191,7 @@ static int bus_append_kill_property(sd_bus_message *m, const char *field, const
if (streq(field, "KillSignal"))
- return bus_append_signal_from_string_try_harder(m, field, eq);
+ return bus_append_signal_from_string(m, field, eq);
return 0;
}
@@ -1315,7 +1300,7 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
r = safe_atoi(word, &val);
if (r < 0) {
- val = signal_from_string_try_harder(word);
+ val = signal_from_string(word);
if (val < 0)
return log_error_errno(r, "Invalid status or signal %s in %s: %m", word, field);
@@ -1808,8 +1793,7 @@ int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
if (r < 0)
return r;
- *ret = d;
- d = NULL;
+ *ret = TAKE_PTR(d);
return 0;
}
@@ -1918,8 +1902,6 @@ finish:
}
static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* extra_args) {
- int r = 0;
-
assert(d->result);
if (!quiet) {
@@ -1937,6 +1919,8 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const*
log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
else if (streq(d->result, "collected"))
log_error("Queued job for %s was garbage collected.", strna(d->name));
+ else if (streq(d->result, "once"))
+ log_error("Unit %s was started already once and can't be started again.", strna(d->name));
else if (!STR_IN_SET(d->result, "done", "skipped")) {
if (d->name) {
_cleanup_free_ char *result = NULL;
@@ -1953,21 +1937,24 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const*
}
if (STR_IN_SET(d->result, "canceled", "collected"))
- r = -ECANCELED;
+ return -ECANCELED;
else if (streq(d->result, "timeout"))
- r = -ETIME;
+ return -ETIME;
else if (streq(d->result, "dependency"))
- r = -EIO;
+ return -EIO;
else if (streq(d->result, "invalid"))
- r = -ENOEXEC;
+ return -ENOEXEC;
else if (streq(d->result, "assert"))
- r = -EPROTO;
+ return -EPROTO;
else if (streq(d->result, "unsupported"))
- r = -EOPNOTSUPP;
- else if (!STR_IN_SET(d->result, "done", "skipped"))
- r = -EIO;
+ return -EOPNOTSUPP;
+ else if (streq(d->result, "once"))
+ return -ESTALE;
+ else if (STR_IN_SET(d->result, "done", "skipped"))
+ return 0;
- return r;
+ log_debug("Unexpected job result, assuming server side newer than us: %s", d->result);
+ return -EIO;
}
int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args) {
@@ -1989,8 +1976,6 @@ int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_ar
if (q < 0 && r == 0)
r = q;
- errno = 0; /* Reset errno explicitly, so that log_debug_errno() will properly print 'Success'
- * for q == 0, instead of whatever is set in errno */
log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
}
@@ -2023,7 +2008,7 @@ int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
return bus_wait_for_jobs(d, quiet, NULL);
}
-int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
+int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, size_t *n_changes) {
const char *type, *path, *source;
int r;
@@ -2468,3 +2453,29 @@ finish:
return r;
}
+
+int unit_load_state(sd_bus *bus, const char *name, char **load_state) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *path = NULL;
+ int r;
+
+ path = unit_dbus_path_from_name(name);
+ if (!path)
+ return log_oom();
+
+ /* This function warns on it's own, because otherwise it'd be awkward to pass
+ * the dbus error message around. */
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.systemd1.Unit",
+ "LoadState",
+ &error,
+ load_state);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get load state of %s: %s", name, bus_error_message(&error, r));
+
+ return 0;
+}
diff --git a/src/shared/bus-unit-util.h b/src/shared/bus-unit-util.h
index 514e6edb76..4fc94b0f4e 100644
--- a/src/shared/bus-unit-util.h
+++ b/src/shared/bus-unit-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "install.h"
#include "output-mode.h"
#include "sd-bus.h"
@@ -54,6 +35,8 @@ int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet);
DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free);
-int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes);
+int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, size_t *n_changes);
int unit_show_processes(sd_bus *bus, const char *unit, const char *cgroup_path, const char *prefix, unsigned n_columns, OutputFlags flags, sd_bus_error *error);
+
+int unit_load_state(sd_bus *bus, const char *name, char **load_state);
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 548e817105..a4f2deba31 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -604,8 +586,7 @@ int bus_connect_system_systemd(sd_bus **_bus) {
if (r < 0)
return r;
- *_bus = bus;
- bus = NULL;
+ *_bus = TAKE_PTR(bus);
return 0;
}
@@ -642,8 +623,7 @@ int bus_connect_user_systemd(sd_bus **_bus) {
if (r < 0)
return r;
- *_bus = bus;
- bus = NULL;
+ *_bus = TAKE_PTR(bus);
return 0;
}
@@ -656,15 +636,15 @@ int bus_connect_user_systemd(sd_bus **_bus) {
printf("%s=" fmt "\n", name, __VA_ARGS__); \
} while (0)
-int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all) {
+int bus_print_property(const char *name, sd_bus_message *m, bool value, bool all) {
char type;
const char *contents;
int r;
assert(name);
- assert(property);
+ assert(m);
- r = sd_bus_message_peek_type(property, &type, &contents);
+ r = sd_bus_message_peek_type(m, &type, &contents);
if (r < 0)
return r;
@@ -673,7 +653,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_STRING: {
const char *s;
- r = sd_bus_message_read_basic(property, type, &s);
+ r = sd_bus_message_read_basic(m, type, &s);
if (r < 0)
return r;
@@ -692,7 +672,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_BOOLEAN: {
int b;
- r = sd_bus_message_read_basic(property, type, &b);
+ r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
return r;
@@ -704,15 +684,17 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_UINT64: {
uint64_t u;
- r = sd_bus_message_read_basic(property, type, &u);
+ r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
return r;
/* Yes, heuristics! But we can change this check
* should it turn out to not be sufficient */
- if (endswith(name, "Timestamp") || STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec")) {
- char timestamp[FORMAT_TIMESTAMP_MAX], *t;
+ if (endswith(name, "Timestamp") ||
+ STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec", "TimeUSec", "RTCTimeUSec")) {
+ char timestamp[FORMAT_TIMESTAMP_MAX];
+ const char *t;
t = format_timestamp(timestamp, sizeof(timestamp), u);
if (t || all)
@@ -731,7 +713,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
else if ((u & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
result = "no";
else {
- r = namespace_flag_to_string_many(u, &s);
+ r = namespace_flags_to_string(u, &s);
if (r < 0)
return r;
@@ -781,7 +763,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_INT64: {
int64_t i;
- r = sd_bus_message_read_basic(property, type, &i);
+ r = sd_bus_message_read_basic(m, type, &i);
if (r < 0)
return r;
@@ -793,7 +775,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_UINT32: {
uint32_t u;
- r = sd_bus_message_read_basic(property, type, &u);
+ r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
return r;
@@ -818,7 +800,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_INT32: {
int32_t i;
- r = sd_bus_message_read_basic(property, type, &i);
+ r = sd_bus_message_read_basic(m, type, &i);
if (r < 0)
return r;
@@ -829,7 +811,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_DOUBLE: {
double d;
- r = sd_bus_message_read_basic(property, type, &d);
+ r = sd_bus_message_read_basic(m, type, &d);
if (r < 0)
return r;
@@ -842,18 +824,18 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
bool first = true;
const char *str;
- r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
if (r < 0)
return r;
- while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
+ while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
bool good;
if (first && !value)
printf("%s=", name);
/* This property has multiple space-separated values, so
- * neither spaces not newlines can be allowed in a value. */
+ * neither spaces nor newlines can be allowed in a value. */
good = str[strcspn(str, " \n")] == '\0';
printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
@@ -868,7 +850,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
if (!first || all)
puts("");
- r = sd_bus_message_exit_container(property);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
@@ -878,7 +860,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
const uint8_t *u;
size_t n;
- r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
+ r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
if (r < 0)
return r;
@@ -900,7 +882,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
uint32_t *u;
size_t n;
- r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
+ r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
if (r < 0)
return r;
@@ -925,81 +907,118 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
return 0;
}
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r;
+int bus_message_print_all_properties(
+ sd_bus_message *m,
+ bus_message_print_t func,
+ char **filter,
+ bool value,
+ bool all,
+ Set **found_properties) {
- assert(bus);
- assert(path);
+ int r;
- r = sd_bus_call_method(bus,
- dest,
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &error,
- &reply,
- "s", "");
- if (r < 0)
- return r;
+ assert(m);
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
if (r < 0)
return r;
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
const char *name;
const char *contents;
- r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
+ r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
if (r < 0)
return r;
+ if (found_properties) {
+ r = set_ensure_allocated(found_properties, &string_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ r = set_put(*found_properties, name);
+ if (r < 0 && r != EEXIST)
+ return log_oom();
+ }
+
if (!filter || strv_find(filter, name)) {
- r = sd_bus_message_peek_type(reply, NULL, &contents);
+ r = sd_bus_message_peek_type(m, NULL, &contents);
if (r < 0)
return r;
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
if (r < 0)
return r;
- r = bus_print_property(name, reply, value, all);
+ if (func)
+ r = func(name, m, value, all);
+ if (!func || r == 0)
+ r = bus_print_property(name, m, value, all);
if (r < 0)
return r;
if (r == 0) {
if (all)
printf("%s=[unprintable]\n", name);
/* skip what we didn't read */
- r = sd_bus_message_skip(reply, contents);
+ r = sd_bus_message_skip(m, contents);
if (r < 0)
return r;
}
- r = sd_bus_message_exit_container(reply);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
} else {
- r = sd_bus_message_skip(reply, "v");
+ r = sd_bus_message_skip(m, "v");
if (r < 0)
return r;
}
- r = sd_bus_message_exit_container(reply);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
}
if (r < 0)
return r;
- r = sd_bus_message_exit_container(reply);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
return 0;
}
+int bus_print_all_properties(
+ sd_bus *bus,
+ const char *dest,
+ const char *path,
+ bus_message_print_t func,
+ char **filter,
+ bool value,
+ bool all,
+ Set **found_properties) {
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r;
+
+ assert(bus);
+ assert(path);
+
+ r = sd_bus_call_method(bus,
+ dest,
+ path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ &error,
+ &reply,
+ "s", "");
+ if (r < 0)
+ return r;
+
+ return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
+}
+
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
sd_id128_t *p = userdata;
const void *v;
@@ -1020,7 +1039,7 @@ int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_err
return 0;
}
-static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
char type;
int r;
@@ -1031,7 +1050,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
switch (type) {
case SD_BUS_TYPE_STRING: {
- char **p = userdata;
+ const char **p = userdata;
const char *s;
r = sd_bus_message_read_basic(m, type, &s);
@@ -1041,7 +1060,11 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
if (isempty(s))
s = NULL;
- return free_and_strdup(p, s);
+ if (flags & BUS_MAP_STRDUP)
+ return free_and_strdup((char **) userdata, s);
+
+ *p = s;
+ return 0;
}
case SD_BUS_TYPE_ARRAY: {
@@ -1052,21 +1075,21 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
if (r < 0)
return r;
- strv_free(*p);
- *p = l;
- l = NULL;
- return 0;
+ return strv_free_and_replace(*p, l);
}
case SD_BUS_TYPE_BOOLEAN: {
- unsigned b;
- int *p = userdata;
+ int b;
r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
return r;
- *p = b;
+ if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
+ *(bool*) userdata = b;
+ else
+ *(int*) userdata = b;
+
return 0;
}
@@ -1111,6 +1134,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
int bus_message_map_all_properties(
sd_bus_message *m,
const struct bus_properties_map *map,
+ unsigned flags,
sd_bus_error *error,
void *userdata) {
@@ -1153,7 +1177,7 @@ int bus_message_map_all_properties(
if (map[i].set)
r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
else
- r = map_basic(sd_bus_message_get_bus(m), member, m, error, v);
+ r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
if (r < 0)
return r;
@@ -1179,6 +1203,7 @@ int bus_message_map_all_properties(
int bus_message_map_properties_changed(
sd_bus_message *m,
const struct bus_properties_map *map,
+ unsigned flags,
sd_bus_error *error,
void *userdata) {
@@ -1188,7 +1213,7 @@ int bus_message_map_properties_changed(
assert(m);
assert(map);
- r = bus_message_map_all_properties(m, map, error, userdata);
+ r = bus_message_map_all_properties(m, map, flags, error, userdata);
if (r < 0)
return r;
@@ -1218,7 +1243,9 @@ int bus_map_all_properties(
const char *destination,
const char *path,
const struct bus_properties_map *map,
+ unsigned flags,
sd_bus_error *error,
+ sd_bus_message **reply,
void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
@@ -1228,6 +1255,7 @@ int bus_map_all_properties(
assert(destination);
assert(path);
assert(map);
+ assert(reply || (flags & BUS_MAP_STRDUP));
r = sd_bus_call_method(
bus,
@@ -1241,7 +1269,14 @@ int bus_map_all_properties(
if (r < 0)
return r;
- return bus_message_map_all_properties(m, map, error, userdata);
+ r = bus_message_map_all_properties(m, map, flags, error, userdata);
+ if (r < 0)
+ return r;
+
+ if (reply)
+ *reply = sd_bus_message_ref(m);
+
+ return r;
}
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
@@ -1260,9 +1295,15 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
case BUS_TRANSPORT_LOCAL:
if (user)
r = sd_bus_default_user(&bus);
- else
- r = sd_bus_default_system(&bus);
+ else {
+ if (sd_booted() <= 0) {
+ /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+ log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
+ return -EHOSTDOWN;
+ }
+ r = sd_bus_default_system(&bus);
+ }
break;
case BUS_TRANSPORT_REMOTE:
@@ -1283,8 +1324,7 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
if (r < 0)
return r;
- *ret = bus;
- bus = NULL;
+ *ret = TAKE_PTR(bus);
return 0;
}
@@ -1304,9 +1344,15 @@ int bus_connect_transport_systemd(BusTransport transport, const char *host, bool
case BUS_TRANSPORT_LOCAL:
if (user)
r = bus_connect_user_systemd(bus);
- else
- r = bus_connect_system_systemd(bus);
+ else {
+ if (sd_booted() <= 0) {
+ /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+ log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
+ return -EHOSTDOWN;
+ }
+ r = bus_connect_system_systemd(bus);
+ }
break;
case BUS_TRANSPORT_REMOTE:
@@ -1353,7 +1399,7 @@ int bus_property_set_bool(
if (r < 0)
return r;
- *(bool *) userdata = !!b;
+ *(bool*) userdata = b;
return 0;
}
@@ -1564,36 +1610,40 @@ int bus_property_get_rlimit(
void *userdata,
sd_bus_error *error) {
+ const char *is_soft;
struct rlimit *rl;
uint64_t u;
rlim_t x;
- const char *is_soft;
assert(bus);
assert(reply);
assert(userdata);
is_soft = endswith(property, "Soft");
+
rl = *(struct rlimit**) userdata;
if (rl)
x = is_soft ? rl->rlim_cur : rl->rlim_max;
else {
struct rlimit buf = {};
+ const char *s, *p;
int z;
- const char *s;
+ /* Chop off "Soft" suffix */
s = is_soft ? strndupa(property, is_soft - property) : property;
- z = rlimit_from_string(strstr(s, "Limit"));
+ /* Skip over any prefix, such as "Default" */
+ assert_se(p = strstr(s, "Limit"));
+
+ z = rlimit_from_string(p + 5);
assert(z >= 0);
- getrlimit(z, &buf);
+ (void) getrlimit(z, &buf);
x = is_soft ? buf.rlim_cur : buf.rlim_max;
}
- /* rlim_t might have different sizes, let's map
- * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
- * all archs */
+ /* rlim_t might have different sizes, let's map RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on all
+ * archs */
u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
return sd_bus_message_append(reply, "t", u);
@@ -1618,7 +1668,7 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
return r;
}
-int bus_open_system_watch_bind(sd_bus **ret) {
+int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
const char *e;
int r;
@@ -1631,6 +1681,12 @@ int bus_open_system_watch_bind(sd_bus **ret) {
if (r < 0)
return r;
+ if (description) {
+ r = sd_bus_set_description(bus, description);
+ if (r < 0)
+ return r;
+ }
+
e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
if (!e)
e = DEFAULT_SYSTEM_BUS_ADDRESS;
@@ -1663,8 +1719,201 @@ int bus_open_system_watch_bind(sd_bus **ret) {
if (r < 0)
return r;
- *ret = bus;
- bus = NULL;
+ *ret = TAKE_PTR(bus);
return 0;
}
+
+struct request_name_data {
+ unsigned n_ref;
+
+ const char *name;
+ uint64_t flags;
+ void *userdata;
+};
+
+static void request_name_destroy_callback(void *userdata) {
+ struct request_name_data *data = userdata;
+
+ assert(data);
+ assert(data->n_ref > 0);
+
+ log_info("%s n_ref=%u", __func__, data->n_ref);
+
+ data->n_ref--;
+ if (data->n_ref == 0)
+ free(data);
+}
+
+static int reload_dbus_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ struct request_name_data *data = userdata;
+ const sd_bus_error *e;
+ int r;
+
+ assert(data);
+ assert(data->name);
+ assert(data->n_ref > 0);
+
+ e = sd_bus_message_get_error(m);
+ if (e) {
+ log_error_errno(sd_bus_error_get_errno(e), "Failed to reload DBus configuration: %s", e->message);
+ return 1;
+ }
+
+ /* Here, use the default request name handler to avoid an infinite loop of reloading and requesting. */
+ r = sd_bus_request_name_async(sd_bus_message_get_bus(m), NULL, data->name, data->flags, NULL, data->userdata);
+ if (r < 0)
+ log_error_errno(r, "Failed to request name: %m");
+
+ return 1;
+}
+
+static int request_name_handler_may_reload_dbus(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ struct request_name_data *data = userdata;
+ uint32_t ret;
+ int r;
+
+ assert(m);
+ assert(data);
+
+ if (sd_bus_message_is_method_error(m, NULL)) {
+ const sd_bus_error *e = sd_bus_message_get_error(m);
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
+
+ if (!sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) {
+ log_debug_errno(sd_bus_error_get_errno(e),
+ "Unable to request name, failing connection: %s",
+ e->message);
+
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ log_debug_errno(sd_bus_error_get_errno(e),
+ "Unable to request name, will retry after reloading DBus configuration: %s",
+ e->message);
+
+ /* If systemd-timesyncd.service enables DynamicUser= and dbus.service
+ * started before the dynamic user is realized, then the DBus policy
+ * about timesyncd has not been enabled yet. So, let's try to reload
+ * DBus configuration, and after that request the name again. Note that it
+ * seems that no privileges are necessary to call the following method. */
+
+ r = sd_bus_call_method_async(
+ sd_bus_message_get_bus(m),
+ &slot,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "ReloadConfig",
+ reload_dbus_handler,
+ data, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to reload DBus configuration: %m");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ data->n_ref ++;
+ assert_se(sd_bus_slot_set_destroy_callback(slot, request_name_destroy_callback) >= 0);
+
+ r = sd_bus_slot_set_floating(slot, true);
+ if (r < 0)
+ return r;
+
+ return 1;
+ }
+
+ r = sd_bus_message_read(m, "u", &ret);
+ if (r < 0)
+ return r;
+
+ switch (ret) {
+
+ case BUS_NAME_ALREADY_OWNER:
+ log_debug("Already owner of requested service name, ignoring.");
+ return 1;
+
+ case BUS_NAME_IN_QUEUE:
+ log_debug("In queue for requested service name.");
+ return 1;
+
+ case BUS_NAME_PRIMARY_OWNER:
+ log_debug("Successfully acquired requested service name.");
+ return 1;
+
+ case BUS_NAME_EXISTS:
+ log_debug("Requested service name already owned, failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ log_debug("Unexpected response from RequestName(), failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+}
+
+int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata) {
+ _cleanup_free_ struct request_name_data *data = NULL;
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
+ int r;
+
+ data = new(struct request_name_data, 1);
+ if (!data)
+ return -ENOMEM;
+
+ *data = (struct request_name_data) {
+ .n_ref = 1,
+ .name = name,
+ .flags = flags,
+ .userdata = userdata,
+ };
+
+ r = sd_bus_request_name_async(bus, &slot, name, flags, request_name_handler_may_reload_dbus, data);
+ if (r < 0)
+ return r;
+
+ assert_se(sd_bus_slot_set_destroy_callback(slot, request_name_destroy_callback) >= 0);
+ TAKE_PTR(data);
+
+ if (ret_slot)
+ *ret_slot = TAKE_PTR(slot);
+ else {
+ r = sd_bus_slot_set_floating(slot, true);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int bus_reply_pair_array(sd_bus_message *m, char **l) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ char **k, **v;
+ int r;
+
+ assert(m);
+
+ /* Reply to the specified message with a message containing a dictionary put together from the specified
+ * strv */
+
+ r = sd_bus_message_new_method_return(m, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "{ss}");
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH_PAIR(k, v, l) {
+ r = sd_bus_message_append(reply, "{ss}", *k, *v);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
index 969a444d83..b400eb81e2 100644
--- a/src/shared/bus-util.h
+++ b/src/shared/bus-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -49,11 +30,17 @@ struct bus_properties_map {
size_t offset;
};
+enum {
+ BUS_MAP_STRDUP = 1 << 0, /* If set, each "s" message is duplicated. Thus, each pointer needs to be freed. */
+ BUS_MAP_BOOLEAN_AS_BOOL = 1 << 1, /* If set, each "b" message is written to a bool pointer. If not set, "b" is written to a int pointer. */
+};
+
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata);
-int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
-int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
-int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
+int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, unsigned flags, sd_bus_error *error, void *userdata);
+int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, unsigned flags, sd_bus_error *error, void *userdata);
+int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map,
+ unsigned flags, sd_bus_error *error, sd_bus_message **reply, void *userdata);
int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name);
@@ -76,8 +63,11 @@ int bus_connect_user_systemd(sd_bus **_bus);
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus);
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
+typedef int (*bus_message_print_t) (const char *name, sd_bus_message *m, bool value, bool all);
+
int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all);
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all);
+int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
+int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error);
@@ -89,7 +79,7 @@ int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface,
assert_cc(sizeof(int) == sizeof(int32_t));
#define bus_property_get_int ((sd_bus_property_get_t) NULL)
-assert_cc(sizeof(unsigned) == sizeof(unsigned));
+assert_cc(sizeof(unsigned) == sizeof(uint32_t));
#define bus_property_get_unsigned ((sd_bus_property_get_t) NULL)
/* On 64bit machines we can use the default serializer for size_t and
@@ -126,7 +116,7 @@ assert_cc(sizeof(mode_t) == sizeof(uint32_t));
int bus_log_parse_error(int r);
int bus_log_create_error(int r);
-#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \
+#define BUS_DEFINE_PROPERTY_GET_GLOBAL(function, bus_type, val) \
int function(sd_bus *bus, \
const char *path, \
const char *interface, \
@@ -135,23 +125,41 @@ int bus_log_create_error(int r);
void *userdata, \
sd_bus_error *error) { \
\
- const char *value; \
- type *field = userdata; \
- int r; \
- \
assert(bus); \
assert(reply); \
- assert(field); \
\
- value = strempty(name##_to_string(*field)); \
+ return sd_bus_message_append(reply, bus_type, val); \
+ }
+
+#define BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, get2) \
+ int function(sd_bus *bus, \
+ const char *path, \
+ const char *interface, \
+ const char *property, \
+ sd_bus_message *reply, \
+ void *userdata, \
+ sd_bus_error *error) { \
\
- r = sd_bus_message_append_basic(reply, 's', value); \
- if (r < 0) \
- return r; \
+ data_type *data = userdata; \
+ \
+ assert(bus); \
+ assert(reply); \
+ assert(data); \
\
- return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ return sd_bus_message_append(reply, bus_type, \
+ get2(get1(data))); \
+ }
+
+#define ident(x) (x)
+#define BUS_DEFINE_PROPERTY_GET(function, bus_type, data_type, get1) \
+ BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, ident)
+
+#define ref(x) (*(x))
+#define BUS_DEFINE_PROPERTY_GET_REF(function, bus_type, data_type, get) \
+ BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, ref, get)
+
+#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \
+ BUS_DEFINE_PROPERTY_GET_REF(function, "s", type, name##_to_string)
#define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \
SD_BUS_PROPERTY(name, "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, realtime), (flags)), \
@@ -164,4 +172,11 @@ int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface
int bus_track_add_name_many(sd_bus_track *t, char **l);
-int bus_open_system_watch_bind(sd_bus **ret);
+int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description);
+static inline int bus_open_system_watch_bind(sd_bus **ret) {
+ return bus_open_system_watch_bind_with_description(ret, NULL);
+}
+
+int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata);
+
+int bus_reply_pair_array(sd_bus_message *m, char **l);
diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
index 0ddae95434..4d1a90bd55 100644
--- a/src/shared/cgroup-show.c
+++ b/src/shared/cgroup-show.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -189,8 +171,7 @@ int show_cgroup_by_path(
free(last);
}
- last = k;
- k = NULL;
+ last = TAKE_PTR(k);
}
if (r < 0)
@@ -358,7 +339,7 @@ int show_cgroup_get_path_and_warn(
const char *m;
m = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
+ r = parse_env_file(NULL, m, NEWLINE, "SCOPE", &unit, NULL);
if (r < 0)
return log_error_errno(r, "Failed to load machine data: %m");
@@ -386,10 +367,8 @@ int show_cgroup_get_path_and_warn(
return log_oom();
*ret = t;
- } else {
- *ret = root;
- root = NULL;
- }
+ } else
+ *ret = TAKE_PTR(root);
return 0;
}
diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h
index efa597aad0..4e510fb73c 100644
--- a/src/shared/cgroup-show.h
+++ b/src/shared/cgroup-show.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c
index 7e2ef4a8eb..08dc7b9e43 100644
--- a/src/shared/clean-ipc.c
+++ b/src/shared/clean-ipc.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
diff --git a/src/shared/clean-ipc.h b/src/shared/clean-ipc.h
index 0ade561b3f..eaff47d4b7 100644
--- a/src/shared/clean-ipc.h
+++ b/src/shared/clean-ipc.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/types.h>
#include "user-util.h"
diff --git a/src/shared/condition.c b/src/shared/condition.c
index a2fd05c425..2969a89b4e 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -39,6 +21,7 @@
#include "cap-list.h"
#include "cgroup-util.h"
#include "condition.h"
+#include "efivars.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
@@ -116,7 +99,7 @@ static int condition_test_kernel_command_line(Condition *c) {
if (r < 0)
return r;
- equal = !!strchr(c->parameter, '=');
+ equal = strchr(c->parameter, '=');
for (p = line;;) {
_cleanup_free_ char *word = NULL;
@@ -264,7 +247,7 @@ static int condition_test_control_group_controller(Condition *c) {
return 1;
}
- return (system_mask & wanted_mask) == wanted_mask;
+ return FLAGS_SET(system_mask, wanted_mask);
}
static int condition_test_group(Condition *c) {
@@ -394,6 +377,8 @@ static int condition_test_security(Condition *c) {
return use_ima();
if (streq(c->parameter, "tomoyo"))
return mac_tomoyo_use();
+ if (streq(c->parameter, "uefi-secureboot"))
+ return is_efi_secure_boot();
return false;
}
@@ -477,7 +462,7 @@ static int condition_test_needs_update(Condition *c) {
uint64_t timestamp;
int r;
- r = parse_env_file(p, NULL, "TIMESTAMP_NSEC", &timestamp_str, NULL);
+ r = parse_env_file(NULL, p, NULL, "TIMESTAMP_NSEC", &timestamp_str, NULL);
if (r < 0) {
log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
return true;
diff --git a/src/shared/condition.h b/src/shared/condition.h
index a84d993370..e69fc366f7 100644
--- a/src/shared/condition.h
+++ b/src/shared/condition.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdio.h>
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 33340b1f20..2d62fdf05d 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <limits.h>
@@ -46,6 +28,7 @@
#include "syslog-util.h"
#include "time-util.h"
#include "utf8.h"
+#include "rlimit-util.h"
int config_item_table_lookup(
const void *table,
@@ -165,7 +148,7 @@ static int next_assignment(
return 0;
}
-/* Parse a variable assignment line */
+/* Parse a single logical line */
static int parse_line(
const char* unit,
const char *filename,
@@ -180,7 +163,7 @@ static int parse_line(
char *l,
void *userdata) {
- char *e;
+ char *e, *include;
assert(filename);
assert(line > 0);
@@ -194,7 +177,8 @@ static int parse_line(
if (strchr(COMMENTS "\n", *l))
return 0;
- if (startswith(l, ".include ")) {
+ include = first_word(l, ".include");
+ if (include) {
_cleanup_free_ char *fn = NULL;
/* .includes are a bad idea, we only support them here
@@ -211,13 +195,20 @@ static int parse_line(
return 0;
}
- fn = file_in_same_dir(filename, strstrip(l+9));
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ ".include directives are deprecated, and support for them will be removed in a future version of systemd. "
+ "Please use drop-in files instead.");
+
+ fn = file_in_same_dir(filename, strstrip(include));
if (!fn)
return -ENOMEM;
return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata);
}
+ if (!utf8_is_valid(l))
+ return log_syntax_invalid_utf8(unit, LOG_WARNING, filename, line, l);
+
if (*l == '[') {
size_t k;
char *n;
@@ -244,8 +235,7 @@ static int parse_line(
*section_line = 0;
*section_ignored = true;
} else {
- free(*section);
- *section = n;
+ free_and_replace(*section, n);
*section_line = line;
*section_ignored = false;
}
@@ -308,8 +298,8 @@ int config_parse(const char *unit,
/* Only log on request, except for ENOENT,
* since we return 0 to the caller. */
if ((flags & CONFIG_PARSE_WARN) || errno == ENOENT)
- log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
- "Failed to open configuration file '%s': %m", filename);
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
+ "Failed to open configuration file '%s': %m", filename);
return errno == ENOENT ? 0 : -errno;
}
}
@@ -403,7 +393,6 @@ int config_parse(const char *unit,
if (flags & CONFIG_PARSE_WARN)
log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
return r;
-
}
continuation = mfree(continuation);
@@ -426,7 +415,6 @@ int config_parse(const char *unit,
if (flags & CONFIG_PARSE_WARN)
log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
return r;
-
}
}
@@ -509,35 +497,7 @@ int config_parse_many(
}
#define DEFINE_PARSER(type, vartype, conv_func) \
- int config_parse_##type( \
- const char *unit, \
- const char *filename, \
- unsigned line, \
- const char *section, \
- unsigned section_line, \
- const char *lvalue, \
- int ltype, \
- const char *rvalue, \
- void *data, \
- void *userdata) { \
- \
- vartype *i = data; \
- int r; \
- \
- assert(filename); \
- assert(lvalue); \
- assert(rvalue); \
- assert(data); \
- \
- r = conv_func(rvalue, i); \
- if (r < 0) \
- log_syntax(unit, LOG_ERR, filename, line, r, \
- "Failed to parse %s value, ignoring: %s", \
- #type, rvalue); \
- \
- return 0; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value")
DEFINE_PARSER(int, int, safe_atoi);
DEFINE_PARSER(long, long, safe_atoli);
@@ -667,7 +627,7 @@ int config_parse_bool(const char* unit,
return fatal ? -ENOEXEC : 0;
}
- *b = !!k;
+ *b = k;
return 0;
}
@@ -716,28 +676,15 @@ int config_parse_string(
void *data,
void *userdata) {
- char **s = data, *n;
+ char **s = data;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (!utf8_is_valid(rvalue)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
- return 0;
- }
-
- if (isempty(rvalue))
- n = NULL;
- else {
- n = strdup(rvalue);
- if (!n)
- return log_oom();
- }
-
- free(*s);
- *s = n;
+ if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
+ return log_oom();
return 0;
}
@@ -754,42 +701,29 @@ int config_parse_path(
void *data,
void *userdata) {
- char **s = data, *n;
+ _cleanup_free_ char *n = NULL;
bool fatal = ltype;
+ char **s = data;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (isempty(rvalue)) {
- n = NULL;
+ if (isempty(rvalue))
goto finalize;
- }
-
- if (!utf8_is_valid(rvalue)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
- return fatal ? -ENOEXEC : 0;
- }
-
- if (!path_is_absolute(rvalue)) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Not an absolute path%s: %s",
- fatal ? "" : ", ignoring", rvalue);
- return fatal ? -ENOEXEC : 0;
- }
n = strdup(rvalue);
if (!n)
return log_oom();
- path_kill_slashes(n);
+ r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE | (fatal ? PATH_CHECK_FATAL : 0), unit, filename, line, lvalue);
+ if (r < 0)
+ return fatal ? -ENOEXEC : 0;
finalize:
- free(*s);
- *s = n;
-
- return 0;
+ return free_and_replace(*s, n);
}
int config_parse_strv(
@@ -830,12 +764,6 @@ int config_parse_strv(
break;
}
- if (!utf8_is_valid(word)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word);
- free(word);
- continue;
- }
-
r = strv_consume(sv, word);
if (r < 0)
return log_oom();
@@ -844,6 +772,41 @@ int config_parse_strv(
return 0;
}
+int config_parse_warn_compat(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Disabled reason = ltype;
+
+ switch(reason) {
+
+ case DISABLED_CONFIGURATION:
+ log_syntax(unit, LOG_DEBUG, filename, line, 0,
+ "Support for option %s= has been disabled at compile time and it is ignored", lvalue);
+ break;
+
+ case DISABLED_LEGACY:
+ log_syntax(unit, LOG_INFO, filename, line, 0,
+ "Support for option %s= has been removed and it is ignored", lvalue);
+ break;
+
+ case DISABLED_EXPERIMENTAL:
+ log_syntax(unit, LOG_INFO, filename, line, 0,
+ "Support for option %s= has not yet been enabled and it is ignored", lvalue);
+ break;
+ }
+
+ return 0;
+}
+
int config_parse_log_facility(
const char *unit,
const char *filename,
@@ -926,7 +889,7 @@ int config_parse_signal(
assert(rvalue);
assert(sig);
- r = signal_from_string_try_harder(rvalue);
+ r = signal_from_string(rvalue);
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue);
return 0;
@@ -1153,8 +1116,112 @@ int config_parse_join_controllers(
}
strv_free_free(*ret);
- *ret = controllers;
- controllers = NULL;
+ *ret = TAKE_PTR(controllers);
+
+ return 0;
+}
+
+int config_parse_mtu(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ uint32_t *mtu = data;
+ int r;
+
+ assert(rvalue);
+ assert(mtu);
+
+ r = parse_mtu(ltype, rvalue, mtu);
+ if (r == -ERANGE) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Maximum transfer unit (MTU) value out of range. Permitted range is %" PRIu32 "…%" PRIu32 ", ignoring: %s",
+ (uint32_t) (ltype == AF_INET6 ? IPV6_MIN_MTU : IPV4_MIN_MTU), (uint32_t) UINT32_MAX,
+ rvalue);
+ return 0;
+ }
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse MTU value '%s', ignoring: %m", rvalue);
+ return 0;
+ }
+
+ return 0;
+}
+
+int config_parse_rlimit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ struct rlimit **rl = data, d = {};
+ int r;
+
+ assert(rvalue);
+ assert(rl);
+
+ r = rlimit_parse(ltype, rvalue, &d);
+ if (r == -EILSEQ) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (rl[ltype])
+ *rl[ltype] = d;
+ else {
+ rl[ltype] = newdup(struct rlimit, &d, 1);
+ if (!rl[ltype])
+ return log_oom();
+ }
+
+ return 0;
+}
+
+int config_parse_permille(const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ unsigned *permille = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(permille);
+
+ r = parse_permille(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse permille value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *permille = (unsigned) r;
return 0;
}
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 908f530713..16f042d894 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
@@ -33,23 +14,32 @@
/* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */
typedef enum ConfigParseFlags {
- CONFIG_PARSE_RELAXED = 1U << 0,
- CONFIG_PARSE_ALLOW_INCLUDE = 1U << 1,
- CONFIG_PARSE_WARN = 1U << 2,
- CONFIG_PARSE_REFUSE_BOM = 1U << 3,
+ CONFIG_PARSE_RELAXED = 1 << 0,
+ CONFIG_PARSE_ALLOW_INCLUDE = 1 << 1,
+ CONFIG_PARSE_WARN = 1 << 2,
+ CONFIG_PARSE_REFUSE_BOM = 1 << 3,
} ConfigParseFlags;
+/* Argument list for parsers of specific configuration settings. */
+#define CONFIG_PARSER_ARGUMENTS \
+ const char *unit, \
+ const char *filename, \
+ unsigned line, \
+ const char *section, \
+ unsigned section_line, \
+ const char *lvalue, \
+ int ltype, \
+ const char *rvalue, \
+ void *data, \
+ void *userdata
+
/* Prototype for a parser for a specific configuration setting */
-typedef int (*ConfigParserCallback)(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
+typedef int (*ConfigParserCallback)(CONFIG_PARSER_ARGUMENTS);
+
+/* A macro declaring the a function prototype, following the typedef above, simply because it's so cumbersomely long
+ * otherwise. (And current emacs gets irritatingly slow when editing files that contain lots of very long function
+ * prototypes on the same screen…) */
+#define CONFIG_PARSER_PROTOTYPE(name) int name(CONFIG_PARSER_ARGUMENTS)
/* Wraps information for parsing a specific configuration variable, to
* be stored in a simple array */
@@ -120,47 +110,103 @@ int config_parse_many(
ConfigParseFlags flags,
void *userdata);
-/* Generic parsers */
-#define GENERIC_PARSER_ARGS \
- const char *unit, \
- const char *filename, \
- unsigned line, \
- const char *section, \
- unsigned section_line, \
- const char *lvalue, \
- int ltype, \
- const char *rvalue, \
- void *data, \
- void *userdata
-int config_parse_int(GENERIC_PARSER_ARGS);
-int config_parse_unsigned(GENERIC_PARSER_ARGS);
-int config_parse_long(GENERIC_PARSER_ARGS);
-int config_parse_uint8(GENERIC_PARSER_ARGS);
-int config_parse_uint16(GENERIC_PARSER_ARGS);
-int config_parse_uint32(GENERIC_PARSER_ARGS);
-int config_parse_uint64(GENERIC_PARSER_ARGS);
-int config_parse_double(GENERIC_PARSER_ARGS);
-int config_parse_iec_size(GENERIC_PARSER_ARGS);
-int config_parse_si_size(GENERIC_PARSER_ARGS);
-int config_parse_iec_uint64(GENERIC_PARSER_ARGS);
-int config_parse_bool(GENERIC_PARSER_ARGS);
-int config_parse_tristate(GENERIC_PARSER_ARGS);
-int config_parse_string(GENERIC_PARSER_ARGS);
-int config_parse_path(GENERIC_PARSER_ARGS);
-int config_parse_strv(GENERIC_PARSER_ARGS);
-int config_parse_sec(GENERIC_PARSER_ARGS);
-int config_parse_nsec(GENERIC_PARSER_ARGS);
-int config_parse_mode(GENERIC_PARSER_ARGS);
-int config_parse_log_facility(GENERIC_PARSER_ARGS);
-int config_parse_log_level(GENERIC_PARSER_ARGS);
-int config_parse_signal(GENERIC_PARSER_ARGS);
-int config_parse_personality(GENERIC_PARSER_ARGS);
-int config_parse_ifname(GENERIC_PARSER_ARGS);
-int config_parse_ip_port(GENERIC_PARSER_ARGS);
-int config_parse_join_controllers(GENERIC_PARSER_ARGS);
-
-#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
- int function(GENERIC_PARSER_ARGS) { \
+CONFIG_PARSER_PROTOTYPE(config_parse_int);
+CONFIG_PARSER_PROTOTYPE(config_parse_unsigned);
+CONFIG_PARSER_PROTOTYPE(config_parse_long);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint8);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint16);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint32);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint64);
+CONFIG_PARSER_PROTOTYPE(config_parse_double);
+CONFIG_PARSER_PROTOTYPE(config_parse_iec_size);
+CONFIG_PARSER_PROTOTYPE(config_parse_si_size);
+CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64);
+CONFIG_PARSER_PROTOTYPE(config_parse_bool);
+CONFIG_PARSER_PROTOTYPE(config_parse_tristate);
+CONFIG_PARSER_PROTOTYPE(config_parse_string);
+CONFIG_PARSER_PROTOTYPE(config_parse_path);
+CONFIG_PARSER_PROTOTYPE(config_parse_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_sec);
+CONFIG_PARSER_PROTOTYPE(config_parse_nsec);
+CONFIG_PARSER_PROTOTYPE(config_parse_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_warn_compat);
+CONFIG_PARSER_PROTOTYPE(config_parse_log_facility);
+CONFIG_PARSER_PROTOTYPE(config_parse_log_level);
+CONFIG_PARSER_PROTOTYPE(config_parse_signal);
+CONFIG_PARSER_PROTOTYPE(config_parse_personality);
+CONFIG_PARSER_PROTOTYPE(config_parse_permille);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifname);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_port);
+CONFIG_PARSER_PROTOTYPE(config_parse_join_controllers);
+CONFIG_PARSER_PROTOTYPE(config_parse_mtu);
+CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
+
+typedef enum Disabled {
+ DISABLED_CONFIGURATION,
+ DISABLED_LEGACY,
+ DISABLED_EXPERIMENTAL,
+} Disabled;
+
+#define DEFINE_CONFIG_PARSE(function, parser, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ int *i = data, r; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
+ \
+ r = parser(rvalue); \
+ if (r < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, r, \
+ msg ", ignoring: %s", rvalue); \
+ return 0; \
+ } \
+ \
+ *i = r; \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_PTR(function, parser, type, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ type *i = data; \
+ int r; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
+ \
+ r = parser(rvalue, i); \
+ if (r < 0) \
+ log_syntax(unit, LOG_ERR, filename, line, r, \
+ msg ", ignoring: %s", rvalue); \
+ \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_ENUM(function, name, type, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ type *i = data, x; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
+ \
+ x = name##_from_string(rvalue); \
+ if (x < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
+ msg ", ignoring: %s", rvalue); \
+ return 0; \
+ } \
+ \
+ *i = x; \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(function, name, type, default_value, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
type *i = data, x; \
\
assert(filename); \
@@ -168,8 +214,14 @@ int config_parse_join_controllers(GENERIC_PARSER_ARGS);
assert(rvalue); \
assert(data); \
\
- if ((x = name##_from_string(rvalue)) < 0) { \
- log_syntax(unit, LOG_ERR, filename, line, -x, \
+ if (isempty(rvalue)) { \
+ *i = default_value; \
+ return 0; \
+ } \
+ \
+ x = name##_from_string(rvalue); \
+ if (x < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
msg ", ignoring: %s", rvalue); \
return 0; \
} \
@@ -178,8 +230,8 @@ int config_parse_join_controllers(GENERIC_PARSER_ARGS);
return 0; \
}
-#define DEFINE_CONFIG_PARSE_ENUMV(function,name,type,invalid,msg) \
- int function(GENERIC_PARSER_ARGS) { \
+#define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
type **enums = data, x, *ys; \
_cleanup_free_ type *xs = NULL; \
const char *word, *state; \
@@ -205,17 +257,17 @@ int config_parse_join_controllers(GENERIC_PARSER_ARGS);
return -ENOMEM; \
\
if ((x = name##_from_string(en)) < 0) { \
- log_syntax(unit, LOG_ERR, filename, line, \
- -x, msg ", ignoring: %s", en); \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
+ msg ", ignoring: %s", en); \
continue; \
} \
\
for (ys = xs; x != invalid && *ys != invalid; ys++) { \
if (*ys == x) { \
- log_syntax(unit, LOG_ERR, filename, \
- line, -x, \
- "Duplicate entry, ignoring: %s", \
- en); \
+ log_syntax(unit, LOG_NOTICE, filename, \
+ line, 0, \
+ "Duplicate entry, ignoring: %s", \
+ en); \
x = invalid; \
} \
} \
@@ -233,9 +285,6 @@ int config_parse_join_controllers(GENERIC_PARSER_ARGS);
*(xs + i) = invalid; \
} \
\
- free(*enums); \
- *enums = xs; \
- xs = NULL; \
- \
+ free_and_replace(*enums, xs); \
return 0; \
}
diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c
index 6d2cc685fa..d117fbfda0 100644
--- a/src/shared/dev-setup.c
+++ b/src/shared/dev-setup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
diff --git a/src/shared/dev-setup.h b/src/shared/dev-setup.h
index 4dd591de0a..f105f2f20f 100644
--- a/src/shared/dev-setup.h
+++ b/src/shared/dev-setup.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sys/types.h>
int dev_setup(const char *prefix, uid_t uid, gid_t gid);
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 86114e3dd1..fa1cf26ee1 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/mount.h>
#include <sys/prctl.h>
@@ -43,6 +25,7 @@
#include "linux-3.13/dm-ioctl.h"
#include "missing.h"
#include "mount-util.h"
+#include "os-util.h"
#include "path-util.h"
#include "process-util.h"
#include "raw-clone.h"
@@ -62,7 +45,7 @@ int probe_filesystem(const char *node, char **ret_fstype) {
* different error otherwise. */
#if HAVE_BLKID
- _cleanup_blkid_free_probe_ blkid_probe b = NULL;
+ _cleanup_(blkid_free_probep) blkid_probe b = NULL;
const char *fstype;
int r;
@@ -108,16 +91,43 @@ not_found:
#endif
}
-int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret) {
+#if HAVE_BLKID
+/* Detect RPMB and Boot partitions, which are not listed by blkid.
+ * See https://github.com/systemd/systemd/issues/5806. */
+static bool device_is_mmc_special_partition(struct udev_device *d) {
+ const char *sysname;
+
+ sysname = udev_device_get_sysname(d);
+ return sysname && startswith(sysname, "mmcblk") &&
+ (endswith(sysname, "rpmb") || endswith(sysname, "boot0") || endswith(sysname, "boot1"));
+}
+
+static bool device_is_block(struct udev_device *d) {
+ const char *ss;
+
+ ss = udev_device_get_subsystem(d);
+ if (!ss)
+ return false;
+
+ return streq(ss, "block");
+}
+#endif
+
+int dissect_image(
+ int fd,
+ const void *root_hash,
+ size_t root_hash_size,
+ DissectImageFlags flags,
+ DissectedImage **ret) {
#if HAVE_BLKID
sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL;
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
bool is_gpt, is_mbr, generic_rw, multiple_generic = false;
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
- _cleanup_blkid_free_probe_ blkid_probe b = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(blkid_free_probep) blkid_probe b = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
_cleanup_free_ char *generic_node = NULL;
sd_id128_t generic_uuid = SD_ID128_NULL;
const char *pttype = NULL;
@@ -216,16 +226,13 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
.rw = true,
.partno = -1,
.architecture = _ARCHITECTURE_INVALID,
- .fstype = t,
- .node = n,
+ .fstype = TAKE_PTR(t),
+ .node = TAKE_PTR(n),
};
- t = n = NULL;
-
m->encrypted = streq(fstype, "crypto_LUKS");
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
@@ -277,8 +284,25 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
/* Count the partitions enumerated by the kernel */
n = 0;
first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first)
+ udev_list_entry_foreach(item, first) {
+ _cleanup_(udev_device_unrefp) struct udev_device *q;
+ dev_t qn;
+
+ q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
+ if (!q)
+ return -errno;
+
+ qn = udev_device_get_devnum(q);
+ if (major(qn) == 0)
+ continue;
+
+ if (!device_is_block(q))
+ continue;
+
+ if (device_is_mmc_special_partition(q))
+ continue;
n++;
+ }
/* Count the partitions enumerated by blkid */
z = blkid_partlist_numof_partitions(pl);
@@ -334,10 +358,10 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *q;
+ _cleanup_(udev_device_unrefp) struct udev_device *q;
unsigned long long pflags;
blkid_partition pp;
- const char *node, *sysname;
+ const char *node;
dev_t qn;
int nr;
@@ -352,11 +376,10 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
if (st.st_rdev == qn)
continue;
- /* Filter out weird MMC RPMB partitions, which cannot reasonably be read, see
- * https://github.com/systemd/systemd/issues/5806 */
- sysname = udev_device_get_sysname(q);
- if (sysname && startswith(sysname, "mmcblk") &&
- (endswith(sysname, "rpmb") || endswith(sysname, "boot0" ) || endswith(sysname, "boot1")))
+ if (!device_is_block(q))
+ continue;
+
+ if (device_is_mmc_special_partition(q))
continue;
node = udev_device_get_devnode(q);
@@ -523,12 +546,10 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
.partno = nr,
.rw = rw,
.architecture = architecture,
- .node = n,
- .fstype = t,
+ .node = TAKE_PTR(n),
+ .fstype = TAKE_PTR(t),
.uuid = id,
};
-
- n = t = NULL;
}
} else if (is_mbr) {
@@ -586,11 +607,9 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
.rw = generic_rw,
.partno = generic_nr,
.architecture = _ARCHITECTURE_INVALID,
- .node = generic_node,
+ .node = TAKE_PTR(generic_node),
.uuid = generic_uuid,
};
-
- generic_node = NULL;
}
}
@@ -633,8 +652,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
p->rw = false;
}
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
#else
@@ -759,6 +777,14 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, flags);
if (r < 0)
return r;
+
+ if (flags & DISSECT_IMAGE_VALIDATE_OS) {
+ r = path_is_os_tree(where);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EMEDIUMTYPE;
+ }
}
if ((flags & DISSECT_IMAGE_MOUNT_ROOT_ONLY))
@@ -865,10 +891,9 @@ static int make_dm_name_and_node(const void *original_node, const char *suffix,
if (!node)
return -ENOMEM;
- *ret_name = name;
- *ret_node = node;
+ *ret_name = TAKE_PTR(name);
+ *ret_node = TAKE_PTR(node);
- name = node = NULL;
return 0;
}
@@ -917,15 +942,11 @@ static int decrypt_partition(
return r == -EPERM ? -EKEYREJECTED : r;
}
- d->decrypted[d->n_decrypted].name = name;
- name = NULL;
-
- d->decrypted[d->n_decrypted].device = cd;
- cd = NULL;
+ d->decrypted[d->n_decrypted].name = TAKE_PTR(name);
+ d->decrypted[d->n_decrypted].device = TAKE_PTR(cd);
d->n_decrypted++;
- m->decrypted_node = node;
- node = NULL;
+ m->decrypted_node = TAKE_PTR(node);
return 0;
}
@@ -979,15 +1000,11 @@ static int verity_partition(
if (r < 0)
return r;
- d->decrypted[d->n_decrypted].name = name;
- name = NULL;
-
- d->decrypted[d->n_decrypted].device = cd;
- cd = NULL;
+ d->decrypted[d->n_decrypted].name = TAKE_PTR(name);
+ d->decrypted[d->n_decrypted].device = TAKE_PTR(cd);
d->n_decrypted++;
- m->decrypted_node = node;
- node = NULL;
+ m->decrypted_node = TAKE_PTR(node);
return 0;
}
@@ -1056,8 +1073,7 @@ int dissected_image_decrypt(
}
}
- *ret = d;
- d = NULL;
+ *ret = TAKE_PTR(d);
return 1;
#else
@@ -1215,11 +1231,9 @@ int root_hash_load(const char *image, void **ret, size_t *ret_size) {
if (l < sizeof(sd_id128_t))
return -EINVAL;
- *ret = k;
+ *ret = TAKE_PTR(k);
*ret_size = l;
- k = NULL;
-
return 1;
}
@@ -1262,17 +1276,15 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
if (r < 0)
goto finish;
- r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS, &child);
+ r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child);
if (r < 0)
goto finish;
if (r == 0) {
- /* Make sure we never propagate to the host */
- if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0)
- _exit(EXIT_FAILURE);
-
- r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
- if (r < 0)
+ r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_VALIDATE_OS);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to mount dissected image: %m");
_exit(EXIT_FAILURE);
+ }
for (k = 0; k < _META_MAX; k++) {
_cleanup_close_ int fd = -1;
@@ -1281,18 +1293,14 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
fds[2*k] = safe_close(fds[2*k]);
NULSTR_FOREACH(p, paths[k]) {
- _cleanup_free_ char *q = NULL;
-
- r = chase_symlinks(p, t, CHASE_PREFIX_ROOT, &q);
- if (r < 0)
- continue;
-
- fd = open(q, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ fd = chase_symlinks_and_open(p, t, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
if (fd >= 0)
break;
}
- if (fd < 0)
+ if (fd < 0) {
+ log_debug_errno(fd, "Failed to read %s file of image, ignoring: %m", paths[k]);
continue;
+ }
r = copy_bytes(fd, fds[2*k+1], (uint64_t) -1, 0);
if (r < 0)
@@ -1379,6 +1387,55 @@ finish:
return r;
}
+int dissect_image_and_warn(
+ int fd,
+ const char *name,
+ const void *root_hash,
+ size_t root_hash_size,
+ DissectImageFlags flags,
+ DissectedImage **ret) {
+
+ _cleanup_free_ char *buffer = NULL;
+ int r;
+
+ if (!name) {
+ r = fd_get_path(fd, &buffer);
+ if (r < 0)
+ return r;
+
+ name = buffer;
+ }
+
+ r = dissect_image(fd, root_hash, root_hash_size, flags, ret);
+
+ switch (r) {
+
+ case -EOPNOTSUPP:
+ return log_error_errno(r, "Dissecting images is not supported, compiled without blkid support.");
+
+ case -ENOPKG:
+ return log_error_errno(r, "Couldn't identify a suitable partition table or file system in '%s'.", name);
+
+ case -EADDRNOTAVAIL:
+ return log_error_errno(r, "No root partition for specified root hash found in '%s'.", name);
+
+ case -ENOTUNIQ:
+ return log_error_errno(r, "Multiple suitable root partitions found in image '%s'.", name);
+
+ case -ENXIO:
+ return log_error_errno(r, "No suitable root partition found in image '%s'.", name);
+
+ case -EPROTONOSUPPORT:
+ return log_error_errno(r, "Device '%s' is loopback block device with partition scanning turned off, please turn it on.", name);
+
+ default:
+ if (r < 0)
+ return log_error_errno(r, "Failed to dissect image '%s': %m", name);
+
+ return r;
+ }
+}
+
static const char *const partition_designator_table[] = {
[PARTITION_ROOT] = "root",
[PARTITION_ROOT_SECONDARY] = "root-secondary",
diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h
index 10e251ff09..0033921fa0 100644
--- a/src/shared/dissect-image.h
+++ b/src/shared/dissect-image.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "sd-id128.h"
@@ -75,6 +56,7 @@ typedef enum DissectImageFlags {
DISSECT_IMAGE_REQUIRE_ROOT = 1 << 5, /* Don't accept disks without root partition */
DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root partition */
DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only non-root partitions */
+ DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifyable as OS images */
} DissectImageFlags;
struct DissectedImage {
@@ -92,6 +74,7 @@ struct DissectedImage {
int probe_filesystem(const char *node, char **ret_fstype);
int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret);
+int dissect_image_and_warn(int fd, const char *name, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret);
DissectedImage* dissected_image_unref(DissectedImage *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index 8c807e0e23..de2fcca8b2 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#if HAVE_LIBIDN2
@@ -295,8 +279,7 @@ int dns_label_escape_new(const char *p, size_t l, char **ret) {
if (r < 0)
return r;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return r;
}
@@ -367,10 +350,7 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX)
return -EINVAL;
- if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
- return 0;
-
- if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0)
+ if (!memory_startswith(encoded, encoded_size, IDNA_ACE_PREFIX))
return 0;
input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
@@ -409,10 +389,9 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
if (a)
p = a;
- else if (b) {
- p = b;
- b = NULL;
- } else
+ else if (b)
+ p = TAKE_PTR(b);
+ else
goto finish;
for (;;) {
@@ -427,8 +406,7 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
if (b) {
/* Now continue with the second string, if there is one */
- p = b;
- b = NULL;
+ p = TAKE_PTR(b);
continue;
}
@@ -478,8 +456,7 @@ finish:
}
ret[n] = 0;
- *_ret = ret;
- ret = NULL;
+ *_ret = TAKE_PTR(ret);
}
return 0;
@@ -601,8 +578,7 @@ int dns_name_endswith(const char *name, const char *suffix) {
/* Not the same, let's jump back, and try with the next label again */
s = suffix;
- n = saved_n;
- saved_n = NULL;
+ n = TAKE_PTR(saved_n);
}
}
}
@@ -677,8 +653,8 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
/* Not the same, let's jump back, and try with the next label again */
s = old_suffix;
- n = saved_after;
- saved_after = saved_before = NULL;
+ n = TAKE_PTR(saved_after);
+ saved_before = NULL;
}
}
@@ -1113,20 +1089,14 @@ finish:
if (r < 0)
return r;
- if (_domain) {
- *_domain = domain;
- domain = NULL;
- }
+ if (_domain)
+ *_domain = TAKE_PTR(domain);
- if (_type) {
- *_type = type;
- type = NULL;
- }
+ if (_type)
+ *_type = TAKE_PTR(type);
- if (_name) {
- *_name = name;
- name = NULL;
- }
+ if (_name)
+ *_name = TAKE_PTR(name);
return 0;
}
@@ -1309,8 +1279,8 @@ int dns_name_apply_idna(const char *name, char **ret) {
}
}
- *ret = t;
- t = NULL;
+ *ret = TAKE_PTR(t);
+
return 1; /* *ret has been written */
}
@@ -1367,8 +1337,7 @@ int dns_name_apply_idna(const char *name, char **ret) {
return -ENOMEM;
buf[n] = 0;
- *ret = buf;
- buf = NULL;
+ *ret = TAKE_PTR(buf);
return 1;
#else
diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h
index cd3dbb7a89..0fd72cb029 100644
--- a/src/shared/dns-domain.h
+++ b/src/shared/dns-domain.h
@@ -2,22 +2,6 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
@@ -38,7 +22,7 @@
#define DNS_HOSTNAME_MAX 253
/* Maximum length of a full hostname, on the wire, including the final NUL byte */
-#define DNS_WIRE_FOMAT_HOSTNAME_MAX 255
+#define DNS_WIRE_FORMAT_HOSTNAME_MAX 255
/* Maximum number of labels per valid hostname */
#define DNS_N_LABELS_MAX 127
diff --git a/src/shared/dropin.c b/src/shared/dropin.c
index f0966874ee..357c66d800 100644
--- a/src/shared/dropin.c
+++ b/src/shared/dropin.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdarg.h>
@@ -128,14 +110,16 @@ static int unit_file_find_dir(
assert(path);
r = chase_symlinks(path, original_root, 0, &chased);
- /* Ignore -ENOENT, after all most units won't have a drop-in dir.
- * Also ignore -ENAMETOOLONG, users are not even able to create
- * the drop-in dir in such case. This mostly happens for device units with long /sys path.
- * */
- if (IN_SET(r, -ENOENT, -ENAMETOOLONG))
+ if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */
return 0;
+ if (r == -ENAMETOOLONG) {
+ /* Also, ignore -ENAMETOOLONG but log about it. After all, users are not even able to create the
+ * drop-in dir in such case. This mostly happens for device units with an overly long /sys path. */
+ log_debug_errno(r, "Path '%s' too long, couldn't canonicalize, ignoring.", path);
+ return 0;
+ }
if (r < 0)
- return log_full_errno(LOG_WARNING, r, "Failed to canonicalize path %s: %m", path);
+ return log_warning_errno(r, "Failed to canonicalize path '%s': %m", path);
r = strv_push(dirs, chased);
if (r < 0)
@@ -153,7 +137,12 @@ static int unit_file_find_dirs(
const char *suffix,
char ***dirs) {
+ _cleanup_free_ char *prefix = NULL, *instance = NULL, *built = NULL;
+ bool is_instance, chopped;
+ const char *dash;
+ UnitType type;
char *path;
+ size_t n;
int r;
assert(unit_path);
@@ -161,26 +150,76 @@ static int unit_file_find_dirs(
assert(suffix);
path = strjoina(unit_path, "/", name, suffix);
-
if (!unit_path_cache || set_get(unit_path_cache, path)) {
r = unit_file_find_dir(original_root, path, dirs);
if (r < 0)
return r;
}
- if (unit_name_is_valid(name, UNIT_NAME_INSTANCE)) {
- /* Also try the template dir */
-
+ is_instance = unit_name_is_valid(name, UNIT_NAME_INSTANCE);
+ if (is_instance) { /* Also try the template dir */
_cleanup_free_ char *template = NULL;
r = unit_name_template(name, &template);
if (r < 0)
return log_error_errno(r, "Failed to generate template from unit name: %m");
- return unit_file_find_dirs(original_root, unit_path_cache, unit_path, template, suffix, dirs);
+ r = unit_file_find_dirs(original_root, unit_path_cache, unit_path, template, suffix, dirs);
+ if (r < 0)
+ return r;
}
- return 0;
+ /* Let's see if there's a "-" prefix for this unit name. If so, let's invoke ourselves for it. This will then
+ * recursively do the same for all our prefixes. i.e. this means given "foo-bar-waldo.service" we'll also
+ * search "foo-bar-.service" and "foo-.service".
+ *
+ * Note the order in which we do it: we traverse up adding drop-ins on each step. This means the more specific
+ * drop-ins may override the more generic drop-ins, which is the intended behaviour. */
+
+ r = unit_name_to_prefix(name, &prefix);
+ if (r < 0)
+ return log_error_errno(r, "Failed to derive unit name prefix from unit name: %m");
+
+ chopped = false;
+ for (;;) {
+ dash = strrchr(prefix, '-');
+ if (!dash) /* No dash? if so we are done */
+ return 0;
+
+ n = (size_t) (dash - prefix);
+ if (n == 0) /* Leading dash? If so, we are done */
+ return 0;
+
+ if (prefix[n+1] != 0 || chopped) {
+ prefix[n+1] = 0;
+ break;
+ }
+
+ /* Trailing dash? If so, chop it off and try again, but not more than once. */
+ prefix[n] = 0;
+ chopped = true;
+ }
+
+ if (!unit_prefix_is_valid(prefix))
+ return 0;
+
+ type = unit_name_to_type(name);
+ if (type < 0) {
+ log_error("Failed to to derive unit type from unit name: %s", name);
+ return -EINVAL;
+ }
+
+ if (is_instance) {
+ r = unit_name_to_instance(name, &instance);
+ if (r < 0)
+ return log_error_errno(r, "Failed to derive unit name instance from unit name: %m");
+ }
+
+ r = unit_name_build_from_type(prefix, instance, type, &built);
+ if (r < 0)
+ return log_error_errno(r, "Failed to build prefix unit name: %m");
+
+ return unit_file_find_dirs(original_root, unit_path_cache, unit_path, built, suffix, dirs);
}
int unit_file_find_dropin_paths(
@@ -193,15 +232,15 @@ int unit_file_find_dropin_paths(
char ***ret) {
_cleanup_strv_free_ char **dirs = NULL;
- Iterator i;
char *t, **p;
+ Iterator i;
int r;
assert(ret);
SET_FOREACH(t, names, i)
STRV_FOREACH(p, lookup_path)
- unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs);
+ (void) unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs);
if (strv_isempty(dirs)) {
*ret = NULL;
diff --git a/src/shared/dropin.h b/src/shared/dropin.h
index 102fc9403c..ae7379beee 100644
--- a/src/shared/dropin.h
+++ b/src/shared/dropin.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "hashmap.h"
#include "macro.h"
#include "set.h"
@@ -49,6 +30,7 @@ static inline int unit_file_find_dropin_conf_paths(
Set *unit_path_cache,
Set *names,
char ***paths) {
+
return unit_file_find_dropin_paths(original_root,
lookup_path,
unit_path_cache,
diff --git a/src/shared/efivars.c b/src/shared/efivars.c
index 9ca51cf750..fcc0db8b0b 100644
--- a/src/shared/efivars.c
+++ b/src/shared/efivars.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -249,8 +231,7 @@ int efi_get_variable(
((char*) buf)[st.st_size - 4] = 0;
((char*) buf)[st.st_size - 4 + 1] = 0;
- *value = buf;
- buf = NULL;
+ *value = TAKE_PTR(buf);
*size = (size_t) st.st_size - 4;
if (attribute)
@@ -428,16 +409,12 @@ int efi_get_boot_option(
}
}
- if (title) {
- *title = s;
- s = NULL;
- }
+ if (title)
+ *title = TAKE_PTR(s);
if (part_uuid)
*part_uuid = p_uuid;
- if (path) {
- *path = p;
- p = NULL;
- }
+ if (path)
+ *path = TAKE_PTR(p);
if (active)
*active = !!(header->attr & LOAD_OPTION_ACTIVE);
@@ -563,8 +540,7 @@ int efi_get_boot_order(uint16_t **order) {
l / sizeof(uint16_t) > INT_MAX)
return -EINVAL;
- *order = buf;
- buf = NULL;
+ *order = TAKE_PTR(buf);
return (int) (l / sizeof(uint16_t));
}
@@ -630,8 +606,8 @@ int efi_get_boot_options(uint16_t **options) {
qsort_safe(list, count, sizeof(uint16_t), cmp_uint16);
- *options = list;
- list = NULL;
+ *options = TAKE_PTR(list);
+
return count;
}
diff --git a/src/shared/efivars.h b/src/shared/efivars.h
index 5b5951321c..dac66da9f8 100644
--- a/src/shared/efivars.h
+++ b/src/shared/efivars.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#if ! ENABLE_EFI
#include <errno.h>
#endif
diff --git a/src/shared/fdset.c b/src/shared/fdset.c
index 9ce1295223..8c852f1137 100644
--- a/src/shared/fdset.c
+++ b/src/shared/fdset.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <alloca.h>
#include <errno.h>
@@ -25,6 +7,7 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fdset.h"
@@ -41,8 +24,8 @@ FDSet *fdset_new(void) {
return MAKE_FDSET(set_new(NULL));
}
-int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds) {
- unsigned i;
+int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds) {
+ size_t i;
FDSet *s;
int r;
@@ -168,8 +151,7 @@ int fdset_new_fill(FDSet **_s) {
}
r = 0;
- *_s = s;
- s = NULL;
+ *_s = TAKE_PTR(s);
finish:
/* We won't close the fds here! */
@@ -219,7 +201,6 @@ int fdset_new_listen_fds(FDSet **_s, bool unset) {
*_s = s;
return 0;
-
fail:
if (s)
set_free(MAKE_SET(s));
@@ -231,10 +212,10 @@ int fdset_close_others(FDSet *fds) {
void *e;
Iterator i;
int *a;
- unsigned j, m;
+ size_t j = 0, m;
- j = 0, m = fdset_size(fds);
- a = alloca(sizeof(int) * m);
+ m = fdset_size(fds);
+ a = newa(int, m);
SET_FOREACH(e, MAKE_SET(fds), i)
a[j++] = PTR_TO_FD(e);
diff --git a/src/shared/fdset.h b/src/shared/fdset.h
index 864ab676f7..d31062b5c6 100644
--- a/src/shared/fdset.h
+++ b/src/shared/fdset.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "hashmap.h"
@@ -37,7 +18,7 @@ int fdset_put_dup(FDSet *s, int fd);
bool fdset_contains(FDSet *s, int fd);
int fdset_remove(FDSet *s, int fd);
-int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds);
+int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds);
int fdset_new_fill(FDSet **ret);
int fdset_new_listen_fds(FDSet **ret, bool unset);
diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c
index a6859462ac..eb4f5ff616 100644
--- a/src/shared/firewall-util.c
+++ b/src/shared/firewall-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
/* Temporary work-around for broken glibc vs. linux kernel header definitions
* This is already fixed upstream, remove this when distributions have updated.
@@ -181,7 +163,6 @@ int fw_add_local_dnat(
uint16_t remote_port,
const union in_addr_union *previous_remote) {
-
_cleanup_(iptc_freep) struct xtc_handle *h = NULL;
struct ipt_entry *entry, *mask;
struct ipt_entry_target *t;
diff --git a/src/shared/firewall-util.h b/src/shared/firewall-util.h
index fd7e3b456e..4fc71dade2 100644
--- a/src/shared/firewall-util.h
+++ b/src/shared/firewall-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdint.h>
diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c
index bcd7b43084..6fd9866c00 100644
--- a/src/shared/fstab-util.c
+++ b/src/shared/fstab-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 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 <errno.h>
#include <mntent.h>
@@ -169,10 +151,8 @@ answer:
*filtered = f;
}
- if (value) {
- *value = v;
- v = NULL;
- }
+ if (value)
+ *value = TAKE_PTR(v);
return !!n;
}
@@ -201,8 +181,7 @@ int fstab_extract_values(const char *opts, const char *name, char ***values) {
return r;
}
- *values = res;
- res = NULL;
+ *values = TAKE_PTR(res);
return !!*values;
}
diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h
index 87f82dcfb4..9820f78ca8 100644
--- a/src/shared/fstab-util.h
+++ b/src/shared/fstab-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 2b0a4ecdc8..8d4fd3267b 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio_ext.h>
diff --git a/src/shared/generator.h b/src/shared/generator.h
index e1c636a218..f0a493b21e 100644
--- a/src/shared/generator.h
+++ b/src/shared/generator.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdio.h>
int generator_open_unit_file(
diff --git a/src/shared/gpt.h b/src/shared/gpt.h
index 7589f6fb7a..fd953fabc7 100644
--- a/src/shared/gpt.h
+++ b/src/shared/gpt.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <endian.h>
#include "sd-id128.h"
@@ -46,7 +27,6 @@
#define GPT_ROOT_ARM_64_VERITY SD_ID128_MAKE(df,33,00,ce,d6,9f,4c,92,97,8c,9b,fb,0f,38,d8,20)
#define GPT_ROOT_IA64_VERITY SD_ID128_MAKE(86,ed,10,d5,b6,07,45,bb,89,57,d3,50,f2,3d,05,71)
-
#if defined(__x86_64__)
# define GPT_ROOT_NATIVE GPT_ROOT_X86_64
# define GPT_ROOT_SECONDARY GPT_ROOT_X86
diff --git a/src/shared/ima-util.c b/src/shared/ima-util.c
index 064f38be6f..0d4ce3cafc 100644
--- a/src/shared/ima-util.c
+++ b/src/shared/ima-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
diff --git a/src/shared/ima-util.h b/src/shared/ima-util.h
index 5633c78be9..8f20741c33 100644
--- a/src/shared/ima-util.h
+++ b/src/shared/ima-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
bool use_ima(void);
diff --git a/src/shared/import-util.c b/src/shared/import-util.c
index 07ba216e93..d53b90796f 100644
--- a/src/shared/import-util.c
+++ b/src/shared/import-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -55,7 +37,6 @@ int import_url_last_component(const char *url, char **ret) {
return 0;
}
-
int import_url_change_last_component(const char *url, const char *suffix, char **ret) {
const char *e;
char *s;
@@ -153,8 +134,7 @@ int raw_strip_suffixes(const char *p, char **ret) {
break;
}
- *ret = q;
- q = NULL;
+ *ret = TAKE_PTR(q);
return 0;
}
diff --git a/src/shared/import-util.h b/src/shared/import-util.h
index 583845b1a4..0f2a5170c8 100644
--- a/src/shared/import-util.h
+++ b/src/shared/import-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "macro.h"
diff --git a/src/shared/initreq.h b/src/shared/initreq.h
index 710037d84b..9b19b5d729 100644
--- a/src/shared/initreq.h
+++ b/src/shared/initreq.h
@@ -55,7 +55,6 @@ struct init_request_bsd {
char reserved[128]; /* For future expansion. */
};
-
/*
* Because of legacy interfaces, "runlevel" and "sleeptime"
* aren't in a separate struct in the union.
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
index aaab2e6665..078d5734be 100644
--- a/src/shared/install-printf.c
+++ b/src/shared/install-printf.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
@@ -50,10 +32,8 @@ static int specifier_prefix_and_instance(char specifier, void *data, void *userd
if (!ans)
return -ENOMEM;
*ret = ans;
- } else {
- *ret = prefix;
- prefix = NULL;
- }
+ } else
+ *ret = TAKE_PTR(prefix);
return 0;
}
@@ -103,6 +83,27 @@ static int specifier_instance(char specifier, void *data, void *userdata, char *
return 0;
}
+static int specifier_last_component(char specifier, void *data, void *userdata, char **ret) {
+ _cleanup_free_ char *prefix = NULL;
+ char *dash;
+ int r;
+
+ r = specifier_prefix(specifier, data, userdata, &prefix);
+ if (r < 0)
+ return r;
+
+ dash = strrchr(prefix, '-');
+ if (dash) {
+ dash = strdup(dash + 1);
+ if (!dash)
+ return -ENOMEM;
+ *ret = dash;
+ } else
+ *ret = TAKE_PTR(prefix);
+
+ return 0;
+}
+
int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) {
/* This is similar to unit_full_printf() but does not support
@@ -126,6 +127,7 @@ int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret)
{ 'N', specifier_prefix_and_instance, NULL },
{ 'p', specifier_prefix, NULL },
{ 'i', specifier_instance, NULL },
+ { 'j', specifier_last_component, NULL },
{ 'U', specifier_user_id, NULL },
{ 'u', specifier_user_name, NULL },
diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h
index d868f65cfa..378b3bfd92 100644
--- a/src/shared/install-printf.h
+++ b/src/shared/install-printf.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "install.h"
int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret);
diff --git a/src/shared/install.c b/src/shared/install.c
index ed5f51cc46..77ae812878 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty <of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -59,8 +41,9 @@
#define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
typedef enum SearchFlags {
- SEARCH_LOAD = 1,
- SEARCH_FOLLOW_CONFIG_SYMLINKS = 2,
+ SEARCH_LOAD = 1 << 0,
+ SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1,
+ SEARCH_DROPIN = 1 << 2,
} SearchFlags;
typedef struct {
@@ -111,8 +94,6 @@ static inline void presets_freep(Presets *p) {
p->n_rules = 0;
}
-static int unit_file_lookup_state(UnitFileScope scope, const LookupPaths *paths, const char *name, UnitFileState *ret);
-
bool unit_type_may_alias(UnitType type) {
return IN_SET(type,
UNIT_SERVICE,
@@ -297,7 +278,7 @@ static int path_is_vendor(const LookupPaths *p, const char *path) {
int unit_file_changes_add(
UnitFileChange **changes,
- unsigned *n_changes,
+ size_t *n_changes,
UnitFileChangeType type,
const char *path,
const char *source) {
@@ -323,9 +304,9 @@ int unit_file_changes_add(
if (!p || (source && !s))
return -ENOMEM;
- path_kill_slashes(p);
+ path_simplify(p, false);
if (s)
- path_kill_slashes(s);
+ path_simplify(s, false);
c[*n_changes] = (UnitFileChange) { type, p, s };
p = s = NULL;
@@ -333,8 +314,8 @@ int unit_file_changes_add(
return 0;
}
-void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
- unsigned i;
+void unit_file_changes_free(UnitFileChange *changes, size_t n_changes) {
+ size_t i;
assert(changes || n_changes == 0);
@@ -346,8 +327,8 @@ void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
free(changes);
}
-void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, unsigned n_changes, bool quiet) {
- unsigned i;
+void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet) {
+ size_t i;
bool logged = false;
assert(changes || n_changes == 0);
@@ -446,7 +427,7 @@ static int create_symlink(
const char *new_path,
bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_free_ char *dest = NULL, *dirname = NULL;
const char *rp;
@@ -530,7 +511,7 @@ static int mark_symlink_for_removal(
if (!n)
return -ENOMEM;
- path_kill_slashes(n);
+ path_simplify(n, false);
r = set_consume(*remove_symlinks_to, n);
if (r == -EEXIST)
@@ -550,7 +531,7 @@ static int remove_marked_symlinks_fd(
bool dry_run,
bool *restart,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
@@ -612,7 +593,7 @@ static int remove_marked_symlinks_fd(
p = path_make_absolute(de->d_name, path);
if (!p)
return -ENOMEM;
- path_kill_slashes(p);
+ path_simplify(p, false);
q = readlink_malloc(p, &dest);
if (q == -ENOENT)
@@ -667,7 +648,7 @@ static int remove_marked_symlinks(
const LookupPaths *lp,
bool dry_run,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_close_ int fd = -1;
bool restart;
@@ -908,16 +889,13 @@ static int find_symlinks_in_scope(
if (r > 0) {
/* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
- r = path_is_config(paths, *p, false);
- if (r < 0)
- return r;
- if (r > 0) {
+ if (path_equal_ptr(*p, paths->persistent_config)) {
/* This is the best outcome, let's return it immediately. */
*state = UNIT_FILE_ENABLED;
return 1;
}
- /* look for globally enablement of user units */
+ /* look for global enablement of user units */
if (scope == UNIT_FILE_USER && path_is_user_config_dir(*p)) {
*state = UNIT_FILE_ENABLED;
return 1;
@@ -932,11 +910,7 @@ static int find_symlinks_in_scope(
enabled_at_all = true;
} else if (same_name_link) {
-
- r = path_is_config(paths, *p, false);
- if (r < 0)
- return r;
- if (r > 0)
+ if (path_equal_ptr(*p, paths->persistent_config))
same_name_link_config = true;
else {
r = path_is_runtime(paths, *p, false);
@@ -1013,7 +987,7 @@ static int install_info_may_process(
UnitFileInstallInfo *i,
const LookupPaths *paths,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
assert(i);
assert(paths);
@@ -1228,6 +1202,7 @@ static int unit_file_load(
InstallContext *c,
UnitFileInstallInfo *info,
const char *path,
+ const char *root_dir,
SearchFlags flags) {
const ConfigTableItem items[] = {
@@ -1248,40 +1223,57 @@ static int unit_file_load(
assert(info);
assert(path);
- type = unit_name_to_type(info->name);
- if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) &&
- !unit_type_may_template(type))
- return log_error_errno(EINVAL, "Unit type %s cannot be templated.", unit_type_to_string(type));
+ if (!(flags & SEARCH_DROPIN)) {
+ /* Loading or checking for the main unit file… */
- if (!(flags & SEARCH_LOAD)) {
- r = lstat(path, &st);
- if (r < 0)
+ type = unit_name_to_type(info->name);
+ if (type < 0)
+ return -EINVAL;
+ if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && !unit_type_may_template(type)) {
+ log_error("Unit type %s cannot be templated.", unit_type_to_string(type));
+ return -EINVAL;
+ }
+
+ if (!(flags & SEARCH_LOAD)) {
+ r = lstat(path, &st);
+ if (r < 0)
+ return -errno;
+
+ if (null_or_empty(&st))
+ info->type = UNIT_FILE_TYPE_MASKED;
+ else if (S_ISREG(st.st_mode))
+ info->type = UNIT_FILE_TYPE_REGULAR;
+ else if (S_ISLNK(st.st_mode))
+ return -ELOOP;
+ else if (S_ISDIR(st.st_mode))
+ return -EISDIR;
+ else
+ return -ENOTTY;
+
+ return 0;
+ }
+
+ fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+ if (fd < 0)
return -errno;
+ } else {
+ /* Operating on a drop-in file. If we aren't supposed to load the unit file drop-ins don't matter, let's hence shortcut this. */
- if (null_or_empty(&st))
- info->type = UNIT_FILE_TYPE_MASKED;
- else if (S_ISREG(st.st_mode))
- info->type = UNIT_FILE_TYPE_REGULAR;
- else if (S_ISLNK(st.st_mode))
- return -ELOOP;
- else if (S_ISDIR(st.st_mode))
- return -EISDIR;
- else
- return -ENOTTY;
+ if (!(flags & SEARCH_LOAD))
+ return 0;
- return 0;
+ fd = chase_symlinks_and_open(path, root_dir, 0, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
+ if (fd < 0)
+ return fd;
}
- /* c is only needed if we actually load the file */
- assert(c);
-
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
if (fstat(fd, &st) < 0)
return -errno;
+
if (null_or_empty(&st)) {
- info->type = UNIT_FILE_TYPE_MASKED;
+ if ((flags & SEARCH_DROPIN) == 0)
+ info->type = UNIT_FILE_TYPE_MASKED;
+
return 0;
}
@@ -1294,6 +1286,9 @@ static int unit_file_load(
return -errno;
fd = -1;
+ /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
+ assert(c);
+
r = config_parse(info->name, path, f,
NULL,
config_item_table_lookup, items,
@@ -1301,7 +1296,8 @@ static int unit_file_load(
if (r < 0)
return log_debug_errno(r, "Failed to parse %s: %m", info->name);
- info->type = UNIT_FILE_TYPE_REGULAR;
+ if ((flags & SEARCH_DROPIN) == 0)
+ info->type = UNIT_FILE_TYPE_REGULAR;
return
(int) strv_length(info->aliases) +
@@ -1319,8 +1315,8 @@ static int unit_file_load_or_readlink(
_cleanup_free_ char *target = NULL;
int r;
- r = unit_file_load(c, info, path, flags);
- if (r != -ELOOP)
+ r = unit_file_load(c, info, path, root_dir, flags);
+ if (r != -ELOOP || (flags & SEARCH_DROPIN))
return r;
/* This is a symlink, let's read it. */
@@ -1383,16 +1379,12 @@ static int unit_file_search(
const LookupPaths *paths,
SearchFlags flags) {
+ const char *dropin_dir_name = NULL, *dropin_template_dir_name = NULL;
+ _cleanup_strv_free_ char **dirs = NULL, **files = NULL;
_cleanup_free_ char *template = NULL;
- _cleanup_strv_free_ char **dirs = NULL;
- _cleanup_strv_free_ char **files = NULL;
- const char *dropin_dir_name = NULL;
- const char *dropin_template_dir_name = NULL;
-
- char **p;
- int r;
- int result;
bool found_unit = false;
+ int r, result;
+ char **p;
assert(info);
assert(paths);
@@ -1420,10 +1412,8 @@ static int unit_file_search(
return -ENOMEM;
r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
-
if (r >= 0) {
- info->path = path;
- path = NULL;
+ info->path = TAKE_PTR(path);
result = r;
found_unit = true;
break;
@@ -1446,8 +1436,7 @@ static int unit_file_search(
r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
if (r >= 0) {
- info->path = path;
- path = NULL;
+ info->path = TAKE_PTR(path);
result = r;
found_unit = true;
break;
@@ -1501,7 +1490,7 @@ static int unit_file_search(
return log_debug_errno(r, "Failed to get list of conf files: %m");
STRV_FOREACH(p, files) {
- r = unit_file_load_or_readlink(c, info, *p, paths->root_dir, flags);
+ r = unit_file_load_or_readlink(c, info, *p, paths->root_dir, flags | SEARCH_DROPIN);
if (r < 0)
return log_debug_errno(r, "Failed to load conf file %s: %m", *p);
}
@@ -1666,7 +1655,7 @@ static int install_info_discover(
SearchFlags flags,
UnitFileInstallInfo **ret,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
UnitFileInstallInfo *i;
int r;
@@ -1690,7 +1679,7 @@ static int install_info_symlink_alias(
const char *config_path,
bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
char **s;
int r = 0, q;
@@ -1725,7 +1714,7 @@ static int install_info_symlink_wants(
char **list,
const char *suffix,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_free_ char *buf = NULL;
const char *n;
@@ -1754,8 +1743,7 @@ static int install_info_symlink_wants(
if (r < 0)
return r;
- path = instance.path;
- instance.path = NULL;
+ path = TAKE_PTR(instance.path);
if (instance.type == UNIT_FILE_TYPE_MASKED) {
unit_file_changes_add(changes, n_changes, -ERFKILL, path, NULL);
@@ -1796,7 +1784,7 @@ static int install_info_symlink_link(
const char *config_path,
bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_free_ char *path = NULL;
int r;
@@ -1825,7 +1813,7 @@ static int install_info_apply(
const char *config_path,
bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
int r, q;
@@ -1862,7 +1850,7 @@ static int install_context_apply(
bool force,
SearchFlags flags,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
UnitFileInstallInfo *i;
int r;
@@ -1923,16 +1911,14 @@ static int install_context_mark_for_removal(
InstallContext *c,
const LookupPaths *paths,
Set **remove_symlinks_to,
- const char *config_path,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
UnitFileInstallInfo *i;
int r;
assert(c);
assert(paths);
- assert(config_path);
/* Marks all items for removal */
@@ -1988,9 +1974,9 @@ int unit_file_mask(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
const char *config_path;
char **i;
int r;
@@ -2034,15 +2020,15 @@ int unit_file_unmask(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
_cleanup_strv_free_ char **todo = NULL;
size_t n_todo = 0, n_allocated = 0;
const char *config_path;
char **i;
- bool dry_run;
+ bool dry_run = !!(flags & UNIT_FILE_DRY_RUN);
int r, q;
assert(scope >= 0);
@@ -2052,73 +2038,71 @@ int unit_file_unmask(
if (r < 0)
return r;
- config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
- if (!config_path)
- return -ENXIO;
-
- dry_run = !!(flags & UNIT_FILE_DRY_RUN);
-
STRV_FOREACH(i, files) {
- _cleanup_free_ char *path = NULL;
-
if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
return -EINVAL;
- path = path_make_absolute(*i, config_path);
- if (!path)
- return -ENOMEM;
+ FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
+ _cleanup_free_ char *path = NULL;
- r = null_or_empty_path(path);
- if (r == -ENOENT)
- continue;
- if (r < 0)
- return r;
- if (r == 0)
- continue;
+ path = path_make_absolute(*i, config_path);
+ if (!path)
+ return -ENOMEM;
- if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
- return -ENOMEM;
+ r = null_or_empty_path(path);
+ if (r == -ENOENT)
+ continue;
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
- todo[n_todo] = strdup(*i);
- if (!todo[n_todo])
- return -ENOMEM;
+ if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
+ return -ENOMEM;
- n_todo++;
+ todo[n_todo] = strdup(*i);
+ if (!todo[n_todo])
+ return -ENOMEM;
+
+ n_todo++;
+ }
}
strv_uniq(todo);
r = 0;
- STRV_FOREACH(i, todo) {
- _cleanup_free_ char *path = NULL;
- const char *rp;
+ FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
+ STRV_FOREACH(i, todo) {
+ _cleanup_free_ char *path = NULL;
+ const char *rp;
- path = path_make_absolute(*i, config_path);
- if (!path)
- return -ENOMEM;
+ path = path_make_absolute(*i, config_path);
+ if (!path)
+ return -ENOMEM;
- if (!dry_run && unlink(path) < 0) {
- if (errno != ENOENT) {
- if (r >= 0)
- r = -errno;
- unit_file_changes_add(changes, n_changes, -errno, path, NULL);
+ if (!dry_run && unlink(path) < 0) {
+ if (errno != ENOENT) {
+ if (r >= 0)
+ r = -errno;
+ unit_file_changes_add(changes, n_changes, -errno, path, NULL);
+ }
+
+ continue;
}
- continue;
- }
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
- unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
+ rp = skip_root(&paths, path);
+ q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
+ if (q < 0)
+ return q;
+ }
- rp = skip_root(&paths, path);
- q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
- if (q < 0)
- return q;
+ q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
+ if (r >= 0)
+ r = q;
}
- q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
- if (r >= 0)
- r = q;
-
return r;
}
@@ -2128,9 +2112,9 @@ int unit_file_link(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_strv_free_ char **todo = NULL;
size_t n_todo = 0, n_allocated = 0;
const char *config_path;
@@ -2228,10 +2212,10 @@ int unit_file_revert(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_strv_free_ char **todo = NULL;
size_t n_todo = 0, n_allocated = 0;
char **i;
@@ -2297,8 +2281,7 @@ int unit_file_revert(
if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
return -ENOMEM;
- todo[n_todo++] = dropin;
- dropin = NULL;
+ todo[n_todo++] = TAKE_PTR(dropin);
}
}
}
@@ -2327,8 +2310,7 @@ int unit_file_revert(
if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
return -ENOMEM;
- todo[n_todo++] = path;
- path = NULL;
+ todo[n_todo++] = TAKE_PTR(path);
}
}
}
@@ -2387,9 +2369,9 @@ int unit_file_add_dependency(
const char *target,
UnitDependency dep,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
UnitFileInstallInfo *i, *target_info;
const char *config_path;
@@ -2461,9 +2443,9 @@ int unit_file_enable(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
const char *config_path;
UnitFileInstallInfo *i;
@@ -2507,11 +2489,12 @@ int unit_file_disable(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+ bool dry_run = !!(flags & UNIT_FILE_DRY_RUN);
const char *config_path;
char **i;
int r;
@@ -2523,10 +2506,6 @@ int unit_file_disable(
if (r < 0)
return r;
- config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
- if (!config_path)
- return -ENXIO;
-
STRV_FOREACH(i, files) {
if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
return -EINVAL;
@@ -2536,11 +2515,17 @@ int unit_file_disable(
return r;
}
- r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, changes, n_changes);
+ r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, changes, n_changes);
if (r < 0)
return r;
- return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, !!(flags & UNIT_FILE_DRY_RUN), changes, n_changes);
+ FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
+ r = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
}
int unit_file_reenable(
@@ -2549,7 +2534,7 @@ int unit_file_reenable(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
char **n;
int r;
@@ -2576,9 +2561,9 @@ int unit_file_set_default(
const char *root_dir,
const char *name,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
UnitFileInstallInfo *i;
const char *new_path;
@@ -2613,7 +2598,7 @@ int unit_file_get_default(
const char *root_dir,
char **name) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
UnitFileInstallInfo *i;
char *n;
@@ -2643,7 +2628,7 @@ int unit_file_get_default(
return 0;
}
-static int unit_file_lookup_state(
+int unit_file_lookup_state(
UnitFileScope scope,
const LookupPaths *paths,
const char *name,
@@ -2737,7 +2722,7 @@ int unit_file_get_state(
const char *name,
UnitFileState *ret) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
int r;
assert(scope >= 0);
@@ -2781,7 +2766,8 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(presets);
- if (scope == UNIT_FILE_SYSTEM)
+ switch (scope) {
+ case UNIT_FILE_SYSTEM:
r = conf_files_list(&files, ".preset", root_dir, 0,
"/etc/systemd/system-preset",
"/run/systemd/system-preset",
@@ -2791,17 +2777,20 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
"/lib/systemd/system-preset",
#endif
NULL);
- else if (scope == UNIT_FILE_GLOBAL)
+ break;
+
+ case UNIT_FILE_GLOBAL:
+ case UNIT_FILE_USER:
r = conf_files_list(&files, ".preset", root_dir, 0,
"/etc/systemd/user-preset",
"/run/systemd/user-preset",
"/usr/local/lib/systemd/user-preset",
"/usr/lib/systemd/user-preset",
NULL);
- else {
- *presets = (Presets){};
+ break;
- return 0;
+ default:
+ assert_not_reached("Invalid unit file scope");
}
if (r < 0)
@@ -2920,45 +2909,45 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
static int execute_preset(
UnitFileScope scope,
+ UnitFileFlags flags,
InstallContext *plus,
InstallContext *minus,
const LookupPaths *paths,
- const char *config_path,
char **files,
UnitFilePresetMode mode,
- bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
- int r;
+ const char *config_path;
+ bool force = !!(flags & UNIT_FILE_FORCE);
+ bool runtime = !!(flags & UNIT_FILE_RUNTIME);
+ int r = 0, q;
assert(plus);
assert(minus);
assert(paths);
- assert(config_path);
if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
- r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, changes, n_changes);
- if (r < 0)
- return r;
+ q = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, changes, n_changes);
+ if (q < 0)
+ return q;
- r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes);
- } else
- r = 0;
+ FOREACH_STRING(config_path, paths->runtime_config, paths->persistent_config) {
+ q = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes);
+ if (r == 0)
+ r = q;
+ }
+ }
if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
- int q;
-
/* Returns number of symlinks that where supposed to be installed. */
- q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes);
- if (r >= 0) {
- if (q < 0)
- r = q;
- else
- r += q;
- }
+ q = install_context_apply(scope, plus, paths,
+ runtime ? paths->runtime_config : paths->persistent_config,
+ force, SEARCH_LOAD, changes, n_changes);
+ if (r == 0)
+ r = q;
}
return r;
@@ -2972,7 +2961,7 @@ static int preset_prepare_one(
const char *name,
Presets presets,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(install_context_done) InstallContext tmp = {};
UnitFileInstallInfo *i;
@@ -3017,12 +3006,11 @@ int unit_file_preset(
char **files,
UnitFilePresetMode mode,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(install_context_done) InstallContext plus = {}, minus = {};
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(presets_freep) Presets presets = {};
- const char *config_path;
char **i;
int r;
@@ -3034,10 +3022,6 @@ int unit_file_preset(
if (r < 0)
return r;
- config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
- if (!config_path)
- return -ENXIO;
-
r = read_presets(scope, root_dir, &presets);
if (r < 0)
return r;
@@ -3048,7 +3032,7 @@ int unit_file_preset(
return r;
}
- return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
+ return execute_preset(scope, flags, &plus, &minus, &paths, files, mode, changes, n_changes);
}
int unit_file_preset_all(
@@ -3057,12 +3041,11 @@ int unit_file_preset_all(
const char *root_dir,
UnitFilePresetMode mode,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(install_context_done) InstallContext plus = {}, minus = {};
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(presets_freep) Presets presets = {};
- const char *config_path = NULL;
char **i;
int r;
@@ -3074,10 +3057,6 @@ int unit_file_preset_all(
if (r < 0)
return r;
- config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
- if (!config_path)
- return -ENXIO;
-
r = read_presets(scope, root_dir, &presets);
if (r < 0)
return r;
@@ -3095,7 +3074,6 @@ int unit_file_preset_all(
}
FOREACH_DIRENT(de, d, return -errno) {
-
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
continue;
@@ -3119,7 +3097,7 @@ int unit_file_preset_all(
}
}
- return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
+ return execute_preset(scope, flags, &plus, &minus, &paths, NULL, mode, changes, n_changes);
}
static void unit_file_list_free_one(UnitFileList *f) {
@@ -3143,7 +3121,7 @@ int unit_file_get_list(
char **states,
char **patterns) {
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
char **i;
int r;
diff --git a/src/shared/install.h b/src/shared/install.h
index 6d7518d72a..e452940991 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef enum UnitFileScope UnitFileScope;
typedef enum UnitFileState UnitFileState;
typedef enum UnitFilePresetMode UnitFilePresetMode;
@@ -77,12 +58,12 @@ enum UnitFileChangeType {
UNIT_FILE_IS_MASKED,
UNIT_FILE_IS_DANGLING,
_UNIT_FILE_CHANGE_TYPE_MAX,
- _UNIT_FILE_CHANGE_INVALID = INT_MIN
+ _UNIT_FILE_CHANGE_TYPE_INVALID = INT_MIN
};
enum UnitFileFlags {
- UNIT_FILE_RUNTIME = 1,
- UNIT_FILE_FORCE = 1 << 1,
+ UNIT_FILE_RUNTIME = 1 << 0,
+ UNIT_FILE_FORCE = 1 << 1,
UNIT_FILE_DRY_RUN = 1 << 2,
};
@@ -96,8 +77,8 @@ struct UnitFileChange {
char *source;
};
-static inline bool unit_file_changes_have_modification(const UnitFileChange* changes, unsigned n_changes) {
- unsigned i;
+static inline bool unit_file_changes_have_modification(const UnitFileChange* changes, size_t n_changes) {
+ size_t i;
for (i = 0; i < n_changes; i++)
if (IN_SET(changes[i].type, UNIT_FILE_SYMLINK, UNIT_FILE_UNLINK))
return true;
@@ -142,21 +123,21 @@ int unit_file_enable(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_disable(
UnitFileScope scope,
UnitFileFlags flags,
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_reenable(
UnitFileScope scope,
UnitFileFlags flags,
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_preset(
UnitFileScope scope,
UnitFileFlags flags,
@@ -164,48 +145,48 @@ int unit_file_preset(
char **files,
UnitFilePresetMode mode,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_preset_all(
UnitFileScope scope,
UnitFileFlags flags,
const char *root_dir,
UnitFilePresetMode mode,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_mask(
UnitFileScope scope,
UnitFileFlags flags,
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_unmask(
UnitFileScope scope,
UnitFileFlags flags,
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_link(
UnitFileScope scope,
UnitFileFlags flags,
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_revert(
UnitFileScope scope,
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_set_default(
UnitFileScope scope,
UnitFileFlags flags,
const char *root_dir,
const char *file,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
int unit_file_get_default(
UnitFileScope scope,
const char *root_dir,
@@ -218,7 +199,13 @@ int unit_file_add_dependency(
const char *target,
UnitDependency dep,
UnitFileChange **changes,
- unsigned *n_changes);
+ size_t *n_changes);
+
+int unit_file_lookup_state(
+ UnitFileScope scope,
+ const LookupPaths *paths,
+ const char *name,
+ UnitFileState *ret);
int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret);
int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name);
@@ -226,9 +213,9 @@ int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *
int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h, char **states, char **patterns);
Hashmap* unit_file_list_free(Hashmap *h);
-int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source);
-void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes);
-void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, unsigned n_changes, bool quiet);
+int unit_file_changes_add(UnitFileChange **changes, size_t *n_changes, UnitFileChangeType type, const char *path, const char *source);
+void unit_file_changes_free(UnitFileChange *changes, size_t n_changes);
+void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet);
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name);
diff --git a/src/shared/journal-util.c b/src/shared/journal-util.c
index 7d53f9dd56..89b76af5b3 100644
--- a/src/shared/journal-util.c
+++ b/src/shared/journal-util.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "acl-util.h"
#include "fs-util.h"
diff --git a/src/shared/journal-util.h b/src/shared/journal-util.h
index f973729a32..404fa53b30 100644
--- a/src/shared/journal-util.h
+++ b/src/shared/journal-util.h
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/shared/libshared.sym b/src/shared/libshared.sym
index e4ae17eede..6a7495adc3 100644
--- a/src/shared/libshared.sym
+++ b/src/shared/libshared.sym
@@ -1,3 +1,3 @@
SD_SHARED {
- global: *;
+ global: *;
};
diff --git a/src/shared/linux/auto_dev-ioctl.h b/src/shared/linux/auto_dev-ioctl.h
index b3555fb2c8..d9838eba49 100644
--- a/src/shared/linux/auto_dev-ioctl.h
+++ b/src/shared/linux/auto_dev-ioctl.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright 2008 Red Hat, Inc. All rights reserved.
- * Copyright 2008 Ian Kent <raven@themaw.net>
+ * Copyright © 2008 Red Hat, Inc. All rights reserved.
+ * Copyright © 2008 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
diff --git a/src/shared/linux/libbpf.h b/src/shared/linux/libbpf.h
index 1989e3a869..ad131fcb12 100644
--- a/src/shared/linux/libbpf.h
+++ b/src/shared/linux/libbpf.h
@@ -104,7 +104,6 @@ struct bpf_insn;
#define BPF_LD_MAP_FD(DST, MAP_FD) \
BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
-
/* Direct packet access, R0 = *(uint *) (skb->data + imm32) */
#define BPF_LD_ABS(SIZE, IMM) \
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 5609e42feb..33afbe2f7f 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -65,7 +47,6 @@ static int print_catalog(FILE *f, sd_journal *j) {
int r;
_cleanup_free_ char *t = NULL, *z = NULL;
-
r = sd_journal_get_catalog(j, &t);
if (r < 0)
return r;
@@ -97,7 +78,6 @@ static int parse_field(const void *data, size_t length, const char *field, size_
nl = length - field_len;
-
buf = newdup_suffix0(char, (const char*) data + field_len, nl);
if (!buf)
return log_oom();
@@ -308,20 +288,14 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou
assert(f);
assert(j);
- r = -ENXIO;
if (realtime)
r = safe_atou64(realtime, &x);
- if (r < 0)
+ if (!realtime || r < 0 || !VALID_REALTIME(x))
r = sd_journal_get_realtime_usec(j, &x);
if (r < 0)
return log_error_errno(r, "Failed to get realtime timestamp: %m");
- if (x > USEC_TIMESTAMP_FORMATTABLE_MAX) {
- log_error("Timestamp cannot be printed");
- return -EINVAL;
- }
-
- if (mode == OUTPUT_SHORT_FULL) {
+ if (IN_SET(mode, OUTPUT_SHORT_FULL, OUTPUT_WITH_UNIT)) {
const char *k;
if (flags & OUTPUT_UTC)
@@ -329,7 +303,7 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou
else
k = format_timestamp(buf, sizeof(buf), x);
if (!k) {
- log_error("Failed to format timestamp.");
+ log_error("Failed to format timestamp: %"PRIu64, x);
return -EINVAL;
}
@@ -406,8 +380,8 @@ static int output_short(
const void *data;
size_t length;
size_t n = 0;
- _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
- size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0;
+ _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL, *unit = NULL, *user_unit = 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, unit_len = 0, user_unit_len = 0;
int p = LOG_INFO;
bool ellipsized = false;
const ParseFieldVec fields[] = {
@@ -420,6 +394,8 @@ static int output_short(
PARSE_FIELD_VEC_ENTRY("SYSLOG_IDENTIFIER=", &identifier, &identifier_len),
PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len),
PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len),
+ PARSE_FIELD_VEC_ENTRY("_SYSTEMD_UNIT=", &unit, &unit_len),
+ PARSE_FIELD_VEC_ENTRY("_SYSTEMD_USER_UNIT=", &user_unit, &user_unit_len),
};
size_t highlight_shifted[] = {highlight ? highlight[0] : 0, highlight ? highlight[1] : 0};
@@ -435,7 +411,6 @@ static int output_short(
sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
-
r = parse_fieldv(data, length, fields, ELEMENTSOF(fields));
if (r < 0)
return r;
@@ -477,7 +452,19 @@ static int output_short(
n += hostname_len + 1;
}
- if (identifier && shall_print(identifier, identifier_len, flags)) {
+ if (mode == OUTPUT_WITH_UNIT && ((unit && shall_print(unit, unit_len, flags)) || (user_unit && shall_print(user_unit, user_unit_len, flags)))) {
+ if (unit) {
+ fprintf(f, " %.*s", (int) unit_len, unit);
+ n += unit_len + 1;
+ }
+ if (user_unit) {
+ if (unit)
+ fprintf(f, "/%.*s", (int) user_unit_len, user_unit);
+ else
+ fprintf(f, " %.*s", (int) user_unit_len, user_unit);
+ n += unit_len + 1;
+ }
+ } else if (identifier && shall_print(identifier, identifier_len, flags)) {
fprintf(f, " %.*s", (int) identifier_len, identifier);
n += identifier_len + 1;
} else if (comm && shall_print(comm, comm_len, flags)) {
@@ -665,10 +652,8 @@ static int output_export(
JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
const char *c;
- /* We already printed the boot id, from the data in
- * the header, hence let's suppress it here */
- if (length >= 9 &&
- startswith(data, "_BOOT_ID="))
+ /* We already printed the boot id from the data in the header, hence let's suppress it here */
+ if (memory_startswith(data, length, "_BOOT_ID="))
continue;
c = memchr(data, '=', length);
@@ -833,15 +818,14 @@ static int output_json(
char *n;
unsigned u;
- if (length >= 9 &&
- memcmp(data, "_BOOT_ID=", 9) == 0)
+ if (memory_startswith(data, length, "_BOOT_ID="))
continue;
eq = memchr(data, '=', length);
if (!eq)
continue;
- n = strndup(data, eq - (const char*) data);
+ n = memdup_suffix0(data, eq - (const char*) data);
if (!n) {
r = log_oom();
goto finish;
@@ -864,12 +848,10 @@ static int output_json(
}
}
}
-
if (r == -EBADMSG) {
log_debug_errno(r, "Skipping message we can't read: %m");
return 0;
}
-
if (r < 0)
return r;
@@ -879,14 +861,14 @@ static int output_json(
SD_JOURNAL_FOREACH_DATA(j, data, length) {
const char *eq;
- char *kk, *n;
+ char *kk;
+ _cleanup_free_ char *n = NULL;
size_t m;
unsigned u;
- /* We already printed the boot id, from the data in
+ /* 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)
+ if (memory_startswith(data, length, "_BOOT_ID="))
continue;
eq = memchr(data, '=', length);
@@ -894,33 +876,24 @@ static int output_json(
continue;
m = eq - (const char*) data;
-
- n = strndup(data, m);
+ n = memdup_suffix0(data, m);
if (!n) {
r = log_oom();
goto finish;
}
- if (output_fields && !set_get(output_fields, n)) {
- free(n);
+ if (output_fields && !set_get(output_fields, n))
continue;
- }
- if (separator) {
- if (mode == OUTPUT_JSON_PRETTY)
- fputs(",\n\t", f);
- else
- fputs(", ", f);
- }
+ if (separator)
+ fputs(mode == OUTPUT_JSON_PRETTY ? ",\n\t" : ", ", f);
u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
- if (u == 0) {
+ if (u == 0)
/* We already printed this, let's jump to the next */
- free(n);
separator = false;
- continue;
- } else if (u == 1) {
+ else if (u == 1) {
/* Field only appears once, output it directly */
json_escape(f, data, m, flags);
@@ -930,12 +903,9 @@ static int output_json(
hashmap_remove(h, n);
free(kk);
- free(n);
separator = true;
- continue;
-
} else {
/* Field appears multiple times, output it as array */
json_escape(f, data, m, flags);
@@ -962,7 +932,6 @@ static int output_json(
hashmap_remove(h, n);
free(kk);
- free(n);
/* Iterate data fields form the beginning */
done = false;
@@ -1068,10 +1037,11 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(
[OUTPUT_JSON] = output_json,
[OUTPUT_JSON_PRETTY] = output_json,
[OUTPUT_JSON_SSE] = output_json,
- [OUTPUT_CAT] = output_cat
+ [OUTPUT_CAT] = output_cat,
+ [OUTPUT_WITH_UNIT] = output_short,
};
-int output_journal(
+int show_journal_entry(
FILE *f,
sd_journal *j,
OutputMode mode,
@@ -1122,14 +1092,15 @@ static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
return 0;
}
-static int show_journal(FILE *f,
- sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
- usec_t not_before,
- unsigned how_many,
- OutputFlags flags,
- bool *ellipsized) {
+int show_journal(
+ FILE *f,
+ sd_journal *j,
+ OutputMode mode,
+ unsigned n_columns,
+ usec_t not_before,
+ unsigned how_many,
+ OutputFlags flags,
+ bool *ellipsized) {
int r;
unsigned line = 0;
@@ -1140,14 +1111,18 @@ static int show_journal(FILE *f,
assert(mode >= 0);
assert(mode < _OUTPUT_MODE_MAX);
- /* Seek to end */
- r = sd_journal_seek_tail(j);
- if (r < 0)
- return log_error_errno(r, "Failed to seek to tail: %m");
+ if (how_many == (unsigned) -1)
+ need_seek = true;
+ else {
+ /* Seek to end */
+ r = sd_journal_seek_tail(j);
+ if (r < 0)
+ return log_error_errno(r, "Failed to seek to tail: %m");
- r = sd_journal_previous_skip(j, how_many);
- if (r < 0)
- return log_error_errno(r, "Failed to skip previous: %m");
+ r = sd_journal_previous_skip(j, how_many);
+ if (r < 0)
+ return log_error_errno(r, "Failed to skip previous: %m");
+ }
for (;;) {
for (;;) {
@@ -1181,7 +1156,7 @@ static int show_journal(FILE *f,
line++;
maybe_print_begin_newline(f, &flags);
- r = output_journal(f, j, mode, n_columns, flags, NULL, NULL, ellipsized);
+ r = show_journal_entry(f, j, mode, n_columns, flags, NULL, NULL, ellipsized);
if (r < 0)
return r;
}
diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h
index c876dcc46a..002d06af84 100644
--- a/src/shared/logs-show.h
+++ b/src/shared/logs-show.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
@@ -32,7 +13,7 @@
#include "time-util.h"
#include "util.h"
-int output_journal(
+int show_journal_entry(
FILE *f,
sd_journal *j,
OutputMode mode,
@@ -41,6 +22,15 @@ int output_journal(
char **output_fields,
size_t highlight[2],
bool *ellipsized);
+int show_journal(
+ FILE *f,
+ sd_journal *j,
+ OutputMode mode,
+ unsigned n_columns,
+ usec_t not_before,
+ unsigned how_many,
+ OutputFlags flags,
+ bool *ellipsized);
int add_match_this_boot(sd_journal *j, const char *machine);
diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c
index 0f3defd581..872c25c3dc 100644
--- a/src/shared/loop-util.c
+++ b/src/shared/loop-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -100,14 +82,11 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) {
return -ENOMEM;
*d = (LoopDevice) {
- .fd = loop,
- .node = loopdev,
+ .fd = TAKE_FD(loop),
+ .node = TAKE_PTR(loopdev),
.nr = nr,
};
- loop = -1;
- loopdev = NULL;
-
*ret = d;
return (*ret)->fd;
diff --git a/src/shared/loop-util.h b/src/shared/loop-util.h
index 7e18e5779d..d78466c5ee 100644
--- a/src/shared/loop-util.h
+++ b/src/shared/loop-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "macro.h"
typedef struct LoopDevice LoopDevice;
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index de67058207..00a5eff670 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dirent.h>
#include <errno.h>
@@ -48,6 +30,7 @@
#include "machine-image.h"
#include "macro.h"
#include "mkdir.h"
+#include "os-util.h"
#include "path-util.h"
#include "rm-rf.h"
#include "string-table.h"
@@ -58,16 +41,31 @@
#include "util.h"
#include "xattr-util.h"
-static const char image_search_path[] =
- "/var/lib/machines\0"
- "/var/lib/container\0" /* legacy */
- "/usr/local/lib/machines\0"
- "/usr/lib/machines\0";
+static const char* const image_search_path[_IMAGE_CLASS_MAX] = {
+ [IMAGE_MACHINE] = "/etc/machines\0" /* only place symlinks here */
+ "/run/machines\0" /* and here too */
+ "/var/lib/machines\0" /* the main place for images */
+ "/var/lib/container\0" /* legacy */
+ "/usr/local/lib/machines\0"
+ "/usr/lib/machines\0",
+
+ [IMAGE_PORTABLE] = "/etc/portables\0" /* only place symlinks here */
+ "/run/portables\0" /* and here too */
+ "/var/lib/portables\0" /* the main place for images */
+ "/usr/local/lib/portables\0"
+ "/usr/lib/portables\0",
+};
Image *image_unref(Image *i) {
if (!i)
return NULL;
+ assert(i->n_ref > 0);
+ i->n_ref--;
+
+ if (i->n_ref > 0)
+ return NULL;
+
free(i->name);
free(i->path);
@@ -78,9 +76,18 @@ Image *image_unref(Image *i) {
return mfree(i);
}
+Image *image_ref(Image *i) {
+ if (!i)
+ return NULL;
+
+ assert(i->n_ref > 0);
+ i->n_ref++;
+
+ return i;
+}
+
static char **image_settings_path(Image *image) {
_cleanup_strv_free_ char **l = NULL;
- char **ret;
const char *fn, *s;
unsigned i = 0;
@@ -104,10 +111,7 @@ static char **image_settings_path(Image *image) {
if (!l[i])
return NULL;
- ret = l;
- l = NULL;
-
- return ret;
+ return TAKE_PTR(l);
}
static char *image_roothash_path(Image *image) {
@@ -142,6 +146,7 @@ static int image_new(
if (!i)
return -ENOMEM;
+ i->n_ref = 1;
i->type = t;
i->read_only = read_only;
i->crtime = crtime;
@@ -157,57 +162,102 @@ static int image_new(
i->path = strjoin(path, "/", filename);
else
i->path = strdup(filename);
-
if (!i->path)
return -ENOMEM;
- path_kill_slashes(i->path);
+ path_simplify(i->path, false);
- *ret = i;
- i = NULL;
+ *ret = TAKE_PTR(i);
return 0;
}
+static int extract_pretty(const char *path, const char *suffix, char **ret) {
+ _cleanup_free_ char *name = NULL;
+ const char *p;
+ size_t n;
+
+ assert(path);
+ assert(ret);
+
+ p = last_path_component(path);
+ n = strcspn(p, "/");
+
+ name = strndup(p, n);
+ if (!name)
+ return -ENOMEM;
+
+ if (suffix) {
+ char *e;
+
+ e = endswith(name, suffix);
+ if (!e)
+ return -EINVAL;
+
+ *e = 0;
+ }
+
+ if (!image_name_is_valid(name))
+ return -EINVAL;
+
+ *ret = TAKE_PTR(name);
+ return 0;
+}
+
static int image_make(
const char *pretty,
int dfd,
const char *path,
const char *filename,
+ const struct stat *st,
Image **ret) {
- struct stat st;
+ _cleanup_free_ char *pretty_buffer = NULL;
+ struct stat stbuf;
bool read_only;
int r;
+ assert(dfd >= 0 || dfd == AT_FDCWD);
assert(filename);
/* We explicitly *do* follow symlinks here, since we want to allow symlinking trees, raw files and block
- * devices into /var/lib/machines/, and treat them normally. */
+ * devices into /var/lib/machines/, and treat them normally.
+ *
+ * This function returns -ENOENT if we can't find the image after all, and -EMEDIUMTYPE if it's not a file we
+ * recognize. */
+
+ if (!st) {
+ if (fstatat(dfd, filename, &stbuf, 0) < 0)
+ return -errno;
- if (fstatat(dfd, filename, &st, 0) < 0)
- return -errno;
+ st = &stbuf;
+ }
read_only =
(path && path_startswith(path, "/usr")) ||
(faccessat(dfd, filename, W_OK, AT_EACCESS) < 0 && errno == EROFS);
- if (S_ISDIR(st.st_mode)) {
+ if (S_ISDIR(st->st_mode)) {
_cleanup_close_ int fd = -1;
unsigned file_attr = 0;
if (!ret)
- return 1;
+ return 0;
+
+ if (!pretty) {
+ r = extract_pretty(filename, NULL, &pretty_buffer);
+ if (r < 0)
+ return r;
- if (!pretty)
- pretty = filename;
+ pretty = pretty_buffer;
+ }
fd = openat(dfd, filename, O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
if (fd < 0)
return -errno;
/* btrfs subvolumes have inode 256 */
- if (st.st_ino == 256) {
+ if (st->st_ino == 256) {
r = btrfs_is_filesystem(fd);
if (r < 0)
@@ -245,7 +295,7 @@ static int image_make(
}
}
- return 1;
+ return 0;
}
}
@@ -266,56 +316,69 @@ static int image_make(
if (r < 0)
return r;
- return 1;
+ return 0;
- } else if (S_ISREG(st.st_mode) && endswith(filename, ".raw")) {
+ } else if (S_ISREG(st->st_mode) && endswith(filename, ".raw")) {
usec_t crtime = 0;
/* It's a RAW disk image */
if (!ret)
- return 1;
+ return 0;
+
+ (void) fd_getcrtime_at(dfd, filename, &crtime, 0);
- fd_getcrtime_at(dfd, filename, &crtime, 0);
+ if (!pretty) {
+ r = extract_pretty(filename, ".raw", &pretty_buffer);
+ if (r < 0)
+ return r;
- if (!pretty)
- pretty = strndupa(filename, strlen(filename) - 4);
+ pretty = pretty_buffer;
+ }
r = image_new(IMAGE_RAW,
pretty,
path,
filename,
- !(st.st_mode & 0222) || read_only,
+ !(st->st_mode & 0222) || read_only,
crtime,
- timespec_load(&st.st_mtim),
+ timespec_load(&st->st_mtim),
ret);
if (r < 0)
return r;
- (*ret)->usage = (*ret)->usage_exclusive = st.st_blocks * 512;
- (*ret)->limit = (*ret)->limit_exclusive = st.st_size;
+ (*ret)->usage = (*ret)->usage_exclusive = st->st_blocks * 512;
+ (*ret)->limit = (*ret)->limit_exclusive = st->st_size;
- return 1;
+ return 0;
- } else if (S_ISBLK(st.st_mode)) {
+ } else if (S_ISBLK(st->st_mode)) {
_cleanup_close_ int block_fd = -1;
uint64_t size = UINT64_MAX;
/* A block device */
if (!ret)
- return 1;
+ return 0;
+
+ if (!pretty) {
+ r = extract_pretty(filename, NULL, &pretty_buffer);
+ if (r < 0)
+ return r;
- if (!pretty)
- pretty = filename;
+ pretty = pretty_buffer;
+ }
block_fd = openat(dfd, filename, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
if (block_fd < 0)
log_debug_errno(errno, "Failed to open block device %s/%s, ignoring: %m", path, filename);
else {
- if (fstat(block_fd, &st) < 0)
+ /* Refresh stat data after opening the node */
+ if (fstat(block_fd, &stbuf) < 0)
return -errno;
- if (!S_ISBLK(st.st_mode)) /* Verify that what we opened is actually what we think it is */
+ st = &stbuf;
+
+ if (!S_ISBLK(st->st_mode)) /* Verify that what we opened is actually what we think it is */
return -ENOTTY;
if (!read_only) {
@@ -328,7 +391,7 @@ static int image_make(
}
if (ioctl(block_fd, BLKGETSIZE64, &size) < 0)
- log_debug_errno(errno, "Failed to issue BLKFLSBUF on device %s/%s, ignoring: %m", path, filename);
+ log_debug_errno(errno, "Failed to issue BLKGETSIZE64 on device %s/%s, ignoring: %m", path, filename);
block_fd = safe_close(block_fd);
}
@@ -337,7 +400,7 @@ static int image_make(
pretty,
path,
filename,
- !(st.st_mode & 0222) || read_only,
+ !(st->st_mode & 0222) || read_only,
0,
0,
ret);
@@ -347,24 +410,27 @@ static int image_make(
if (size != 0 && size != UINT64_MAX)
(*ret)->usage = (*ret)->usage_exclusive = (*ret)->limit = (*ret)->limit_exclusive = size;
- return 1;
+ return 0;
}
- return 0;
+ return -EMEDIUMTYPE;
}
-int image_find(const char *name, Image **ret) {
+int image_find(ImageClass class, const char *name, Image **ret) {
const char *path;
int r;
+ assert(class >= 0);
+ assert(class < _IMAGE_CLASS_MAX);
assert(name);
/* There are no images with invalid names */
if (!image_name_is_valid(name))
- return 0;
+ return -ENOENT;
- NULSTR_FOREACH(path, image_search_path) {
+ NULSTR_FOREACH(path, image_search_path[class]) {
_cleanup_closedir_ DIR *d = NULL;
+ struct stat st;
d = opendir(path);
if (!d) {
@@ -374,37 +440,90 @@ int image_find(const char *name, Image **ret) {
return -errno;
}
- r = image_make(NULL, dirfd(d), path, name, ret);
- if (IN_SET(r, 0, -ENOENT)) {
+ /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people to
+ * symlink block devices into the search path */
+ if (fstatat(dirfd(d), name, &st, 0) < 0) {
_cleanup_free_ char *raw = NULL;
+ if (errno != ENOENT)
+ return -errno;
+
raw = strappend(name, ".raw");
if (!raw)
return -ENOMEM;
- r = image_make(NULL, dirfd(d), path, raw, ret);
- if (IN_SET(r, 0, -ENOENT))
+ if (fstatat(dirfd(d), raw, &st, 0) < 0) {
+
+ if (errno == ENOENT)
+ continue;
+
+ return -errno;
+ }
+
+ if (!S_ISREG(st.st_mode))
+ continue;
+
+ r = image_make(name, dirfd(d), path, raw, &st, ret);
+
+ } else {
+ if (!S_ISDIR(st.st_mode) && !S_ISBLK(st.st_mode))
continue;
+
+ r = image_make(name, dirfd(d), path, name, &st, ret);
}
+ if (IN_SET(r, -ENOENT, -EMEDIUMTYPE))
+ continue;
if (r < 0)
return r;
+ if (ret)
+ (*ret)->discoverable = true;
+
return 1;
}
- if (streq(name, ".host"))
- return image_make(".host", AT_FDCWD, NULL, "/", ret);
+ if (class == IMAGE_MACHINE && streq(name, ".host")) {
+ r = image_make(".host", AT_FDCWD, NULL, "/", NULL, ret);
+ if (r < 0)
+ return r;
- return 0;
+ if (ret)
+ (*ret)->discoverable = true;
+
+ return r;
+ }
+
+ return -ENOENT;
};
-int image_discover(Hashmap *h) {
+int image_from_path(const char *path, Image **ret) {
+
+ /* Note that we don't set the 'discoverable' field of the returned object, because we don't check here whether
+ * the image is in the image search path. And if it is we don't know if the path we used is actually not
+ * overridden by another, different image earlier in the search path */
+
+ if (path_equal(path, "/"))
+ return image_make(".host", AT_FDCWD, NULL, "/", NULL, ret);
+
+ return image_make(NULL, AT_FDCWD, NULL, path, NULL, ret);
+}
+
+int image_find_harder(ImageClass class, const char *name_or_path, Image **ret) {
+ if (image_name_is_valid(name_or_path))
+ return image_find(class, name_or_path, ret);
+
+ return image_from_path(name_or_path, ret);
+}
+
+int image_discover(ImageClass class, Hashmap *h) {
const char *path;
int r;
+ assert(class >= 0);
+ assert(class < _IMAGE_CLASS_MAX);
assert(h);
- NULSTR_FOREACH(path, image_search_path) {
+ NULSTR_FOREACH(path, image_search_path[class]) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
@@ -418,19 +537,53 @@ int image_discover(Hashmap *h) {
FOREACH_DIRENT_ALL(de, d, return -errno) {
_cleanup_(image_unrefp) Image *image = NULL;
+ _cleanup_free_ char *truncated = NULL;
+ const char *pretty;
+ struct stat st;
- if (!image_name_is_valid(de->d_name))
+ if (dot_or_dot_dot(de->d_name))
continue;
- if (hashmap_contains(h, de->d_name))
+ /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people
+ * to symlink block devices into the search path */
+ if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
+ if (errno == ENOENT)
+ continue;
+
+ return -errno;
+ }
+
+ if (S_ISREG(st.st_mode)) {
+ const char *e;
+
+ e = endswith(de->d_name, ".raw");
+ if (!e)
+ continue;
+
+ truncated = strndup(de->d_name, e - de->d_name);
+ if (!truncated)
+ return -ENOMEM;
+
+ pretty = truncated;
+ } else if (S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode))
+ pretty = de->d_name;
+ else
continue;
- r = image_make(NULL, dirfd(d), path, de->d_name, &image);
- if (IN_SET(r, 0, -ENOENT))
+ if (!image_name_is_valid(pretty))
+ continue;
+
+ if (hashmap_contains(h, pretty))
+ continue;
+
+ r = image_make(pretty, dirfd(d), path, de->d_name, &st, &image);
+ if (IN_SET(r, -ENOENT, -EMEDIUMTYPE))
continue;
if (r < 0)
return r;
+ image->discoverable = true;
+
r = hashmap_put(h, image->name, image);
if (r < 0)
return r;
@@ -439,26 +592,27 @@ int image_discover(Hashmap *h) {
}
}
- if (!hashmap_contains(h, ".host")) {
+ if (class == IMAGE_MACHINE && !hashmap_contains(h, ".host")) {
_cleanup_(image_unrefp) Image *image = NULL;
- r = image_make(".host", AT_FDCWD, NULL, "/", &image);
+ r = image_make(".host", AT_FDCWD, NULL, "/", NULL, &image);
if (r < 0)
return r;
+ image->discoverable = true;
+
r = hashmap_put(h, image->name, image);
if (r < 0)
return r;
image = NULL;
-
}
return 0;
}
int image_remove(Image *i) {
- _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
_cleanup_strv_free_ char **settings = NULL;
_cleanup_free_ char *roothash = NULL;
char **j;
@@ -549,7 +703,7 @@ static int rename_auxiliary_file(const char *path, const char *new_name, const c
}
int image_rename(Image *i, const char *new_name) {
- _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT, name_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT, name_lock = LOCK_FILE_INIT;
_cleanup_free_ char *new_path = NULL, *nn = NULL, *roothash = NULL;
_cleanup_strv_free_ char **settings = NULL;
unsigned file_attr = 0;
@@ -584,11 +738,11 @@ int image_rename(Image *i, const char *new_name) {
if (r < 0)
return r;
- r = image_find(new_name, NULL);
- if (r < 0)
- return r;
- if (r > 0)
+ r = image_find(IMAGE_MACHINE, new_name, NULL);
+ if (r >= 0)
return -EEXIST;
+ if (r != -ENOENT)
+ return r;
switch (i->type) {
@@ -670,7 +824,7 @@ static int clone_auxiliary_file(const char *path, const char *new_name, const ch
}
int image_clone(Image *i, const char *new_name, bool read_only) {
- _cleanup_release_lock_file_ LockFile name_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile name_lock = LOCK_FILE_INIT;
_cleanup_strv_free_ char **settings = NULL;
_cleanup_free_ char *roothash = NULL;
const char *new_path;
@@ -697,11 +851,11 @@ int image_clone(Image *i, const char *new_name, bool read_only) {
if (r < 0)
return r;
- r = image_find(new_name, NULL);
- if (r < 0)
- return r;
- if (r > 0)
+ r = image_find(IMAGE_MACHINE, new_name, NULL);
+ if (r >= 0)
return -EEXIST;
+ if (r != -ENOENT)
+ return r;
switch (i->type) {
@@ -753,7 +907,7 @@ int image_clone(Image *i, const char *new_name, bool read_only) {
}
int image_read_only(Image *i, bool b) {
- _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
int r;
assert(i);
@@ -883,8 +1037,7 @@ int image_path_lock(const char *path, int operation, LockFile *global, LockFile
r = make_lock_file_for(path, operation, &t);
if (r < 0) {
if ((operation & LOCK_SH) && r == -EROFS)
- log_debug_errno(r, "Failed to create shared "
- "lock for %s: %m", path);
+ log_debug_errno(r, "Failed to create shared lock for '%s', ignoring: %m", path);
else
return r;
}
@@ -925,7 +1078,7 @@ int image_set_limit(Image *i, uint64_t referenced_max) {
}
int image_read_metadata(Image *i) {
- _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
int r;
assert(i);
@@ -943,7 +1096,7 @@ int image_read_metadata(Image *i) {
_cleanup_free_ char *hostname = NULL;
_cleanup_free_ char *path = NULL;
- r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT, &path);
+ r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name);
else if (r >= 0) {
@@ -954,7 +1107,7 @@ int image_read_metadata(Image *i) {
path = mfree(path);
- r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT, &path);
+ r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name);
else if (r >= 0) {
@@ -972,7 +1125,7 @@ int image_read_metadata(Image *i) {
path = mfree(path);
- r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT, &path);
+ r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to chase /etc/machine-info in image %s: %m", i->name);
else if (r >= 0) {
@@ -981,18 +1134,9 @@ int image_read_metadata(Image *i) {
log_debug_errno(r, "Failed to parse machine-info data of %s: %m", i->name);
}
- path = mfree(path);
-
- r = chase_symlinks("/etc/os-release", i->path, CHASE_PREFIX_ROOT, &path);
- if (r == -ENOENT)
- r = chase_symlinks("/usr/lib/os-release", i->path, CHASE_PREFIX_ROOT, &path);
- if (r < 0 && r != -ENOENT)
- log_debug_errno(r, "Failed to chase os-release in image: %m");
- else if (r >= 0) {
- r = load_env_file_pairs(NULL, path, NULL, &os_release);
- if (r < 0)
- log_debug_errno(r, "Failed to parse os-release data of %s: %m", i->name);
- }
+ r = load_os_release_pairs(i->path, &os_release);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read os-release in image, ignoring: %m");
free_and_replace(i->hostname, hostname);
i->machine_id = machine_id;
@@ -1078,6 +1222,35 @@ bool image_name_is_valid(const char *s) {
return true;
}
+bool image_in_search_path(ImageClass class, const char *image) {
+ const char *path;
+
+ assert(image);
+
+ NULSTR_FOREACH(path, image_search_path[class]) {
+ const char *p;
+ size_t k;
+
+ p = path_startswith(image, path);
+ if (!p)
+ continue;
+
+ /* Make sure there's a filename following */
+ k = strcspn(p, "/");
+ if (k == 0)
+ continue;
+
+ p += k;
+
+ /* Accept trailing slashes */
+ if (p[strspn(p, "/")] == 0)
+ return true;
+
+ }
+
+ return false;
+}
+
static const char* const image_type_table[_IMAGE_TYPE_MAX] = {
[IMAGE_DIRECTORY] = "directory",
[IMAGE_SUBVOLUME] = "subvolume",
diff --git a/src/shared/machine-image.h b/src/shared/machine-image.h
index 3df9a29a24..2e38522acd 100644
--- a/src/shared/machine-image.h
+++ b/src/shared/machine-image.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stdint.h>
@@ -30,6 +11,13 @@
#include "string-util.h"
#include "time-util.h"
+typedef enum ImageClass {
+ IMAGE_MACHINE,
+ IMAGE_PORTABLE,
+ _IMAGE_CLASS_MAX,
+ _IMAGE_CLASS_INVALID = -1
+} ImageClass;
+
typedef enum ImageType {
IMAGE_DIRECTORY,
IMAGE_SUBVOLUME,
@@ -40,6 +28,8 @@ typedef enum ImageType {
} ImageType;
typedef struct Image {
+ unsigned n_ref;
+
ImageType type;
char *name;
char *path;
@@ -58,12 +48,15 @@ typedef struct Image {
char **machine_info;
char **os_release;
- bool metadata_valid;
+ bool metadata_valid:1;
+ bool discoverable:1; /* true if we know for sure that image_find() would find the image given just the short name */
void *userdata;
} Image;
Image *image_unref(Image *i);
+Image *image_ref(Image *i);
+
static inline Hashmap* image_hashmap_free(Hashmap *map) {
return hashmap_free_with_destructor(map, image_unref);
}
@@ -71,8 +64,10 @@ static inline Hashmap* image_hashmap_free(Hashmap *map) {
DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, image_hashmap_free);
-int image_find(const char *name, Image **ret);
-int image_discover(Hashmap *map);
+int image_find(ImageClass class, const char *name, Image **ret);
+int image_from_path(const char *path, Image **ret);
+int image_find_harder(ImageClass class, const char *name_or_path, Image **ret);
+int image_discover(ImageClass class, Hashmap *map);
int image_remove(Image *i);
int image_rename(Image *i, const char *new_name);
@@ -91,6 +86,8 @@ int image_set_limit(Image *i, uint64_t referenced_max);
int image_read_metadata(Image *i);
+bool image_in_search_path(ImageClass class, const char *image);
+
static inline bool IMAGE_IS_HIDDEN(const struct Image *i) {
assert(i);
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index 031d443e9e..53c5609f9b 100644
--- a/src/shared/machine-pool.c
+++ b/src/shared/machine-pool.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -89,11 +71,8 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) {
* /var/lib/machines. */
fd = open("/var/lib/machines.raw", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
- if (fd >= 0) {
- r = fd;
- fd = -1;
- return r;
- }
+ if (fd >= 0)
+ return TAKE_FD(fd);
if (errno != ENOENT)
return sd_bus_error_set_errnof(error, errno, "Failed to open /var/lib/machines.raw: %m");
@@ -162,10 +141,7 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) {
goto fail;
}
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
fail:
unlink_noerrno(tmp);
@@ -177,7 +153,7 @@ fail:
}
int setup_machine_directory(uint64_t size, sd_bus_error *error) {
- _cleanup_release_lock_file_ LockFile lock_file = LOCK_FILE_INIT;
+ _cleanup_(release_lock_file) LockFile lock_file = LOCK_FILE_INIT;
struct loop_info64 info = {
.lo_flags = LO_FLAGS_AUTOCLEAR,
};
diff --git a/src/shared/machine-pool.h b/src/shared/machine-pool.h
index 6e390521e8..fd09296f23 100644
--- a/src/shared/machine-pool.h
+++ b/src/shared/machine-pool.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdint.h>
#include "sd-bus.h"
diff --git a/src/shared/meson.build b/src/shared/meson.build
index 91fecf896c..54e77e9af6 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -1,21 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-shared_sources = '''
+shared_sources = files('''
acl-util.h
acpi-fpdt.c
acpi-fpdt.h
@@ -82,8 +67,6 @@ shared_sources = '''
nsflags.h
output-mode.c
output-mode.h
- pager.c
- pager.h
path-lookup.c
path-lookup.h
ptyfwd.c
@@ -119,25 +102,25 @@ shared_sources = '''
watchdog.c
watchdog.h
wireguard-netlink.h
-'''.split()
+'''.split())
test_tables_h = files('test-tables.h')
shared_sources += [test_tables_h]
if conf.get('HAVE_ACL') == 1
- shared_sources += ['acl-util.c']
+ shared_sources += files('acl-util.c')
endif
if conf.get('ENABLE_UTMP') == 1
- shared_sources += ['utmp-wtmp.c']
+ shared_sources += files('utmp-wtmp.c')
endif
if conf.get('HAVE_SECCOMP') == 1
- shared_sources += ['seccomp-util.c']
+ shared_sources += files('seccomp-util.c')
endif
if conf.get('HAVE_LIBIPTC') == 1
- shared_sources += ['firewall-util.c']
+ shared_sources += files('firewall-util.c')
endif
libshared_name = 'systemd-shared-@0@'.format(meson.project_version())
diff --git a/src/shared/nsflags.c b/src/shared/nsflags.c
index 05ec9feb8d..a5beb9200f 100644
--- a/src/shared/nsflags.c
+++ b/src/shared/nsflags.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sched.h>
@@ -38,32 +20,7 @@ const struct namespace_flag_map namespace_flag_map[] = {
{}
};
-const char* namespace_flag_to_string(unsigned long flag) {
- unsigned i;
-
- flag &= NAMESPACE_FLAGS_ALL;
-
- for (i = 0; namespace_flag_map[i].name; i++)
- if (flag == namespace_flag_map[i].flag)
- return namespace_flag_map[i].name;
-
- return NULL; /* either unknown namespace flag, or a combination of many. This call supports neither. */
-}
-
-unsigned long namespace_flag_from_string(const char *name) {
- unsigned i;
-
- if (isempty(name))
- return 0;
-
- for (i = 0; namespace_flag_map[i].name; i++)
- if (streq(name, namespace_flag_map[i].name))
- return namespace_flag_map[i].flag;
-
- return 0;
-}
-
-int namespace_flag_from_string_many(const char *name, unsigned long *ret) {
+int namespace_flags_from_string(const char *name, unsigned long *ret) {
unsigned long flags = 0;
int r;
@@ -71,7 +28,8 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) {
for (;;) {
_cleanup_free_ char *word = NULL;
- unsigned long f;
+ unsigned long f = 0;
+ unsigned i;
r = extract_first_word(&name, &word, NULL, 0);
if (r < 0)
@@ -79,7 +37,12 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) {
if (r == 0)
break;
- f = namespace_flag_from_string(word);
+ for (i = 0; namespace_flag_map[i].name; i++)
+ if (streq(word, namespace_flag_map[i].name)) {
+ f = namespace_flag_map[i].flag;
+ break;
+ }
+
if (f == 0)
return -EINVAL;
@@ -90,7 +53,7 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) {
return 0;
}
-int namespace_flag_to_string_many(unsigned long flags, char **ret) {
+int namespace_flags_to_string(unsigned long flags, char **ret) {
_cleanup_free_ char *s = NULL;
unsigned i;
@@ -98,14 +61,8 @@ int namespace_flag_to_string_many(unsigned long flags, char **ret) {
if ((flags & namespace_flag_map[i].flag) != namespace_flag_map[i].flag)
continue;
- if (!s) {
- s = strdup(namespace_flag_map[i].name);
- if (!s)
- return -ENOMEM;
- } else {
- if (!strextend(&s, " ", namespace_flag_map[i].name, NULL))
- return -ENOMEM;
- }
+ if (!strextend_with_separator(&s, " ", namespace_flag_map[i].name, NULL))
+ return -ENOMEM;
}
if (!s) {
@@ -114,8 +71,7 @@ int namespace_flag_to_string_many(unsigned long flags, char **ret) {
return -ENOMEM;
}
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
diff --git a/src/shared/nsflags.h b/src/shared/nsflags.h
index 51bc590621..7cc26a441d 100644
--- a/src/shared/nsflags.h
+++ b/src/shared/nsflags.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sched.h>
#include "missing.h"
@@ -37,17 +18,10 @@
CLONE_NEWUSER| \
CLONE_NEWUTS))
-const char* namespace_flag_to_string(unsigned long flag);
-unsigned long namespace_flag_from_string(const char *name);
-int namespace_flag_from_string_many(const char *name, unsigned long *ret);
-int namespace_flag_to_string_many(unsigned long flags, char **ret);
-
-static inline int namespace_flag_to_string_many_with_check(unsigned long n, char **s) {
- if ((n & NAMESPACE_FLAGS_ALL) != n)
- return -EINVAL;
+#define NAMESPACE_FLAGS_INITIAL ((unsigned long) -1)
- return namespace_flag_to_string_many(n, s);
-}
+int namespace_flags_from_string(const char *name, unsigned long *ret);
+int namespace_flags_to_string(unsigned long flags, char **ret);
struct namespace_flag_map {
unsigned long flag;
diff --git a/src/shared/output-mode.c b/src/shared/output-mode.c
index 5256e917a3..bb33ba3d10 100644
--- a/src/shared/output-mode.c
+++ b/src/shared/output-mode.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "output-mode.h"
#include "string-table.h"
@@ -34,7 +16,8 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
[OUTPUT_JSON] = "json",
[OUTPUT_JSON_PRETTY] = "json-pretty",
[OUTPUT_JSON_SSE] = "json-sse",
- [OUTPUT_CAT] = "cat"
+ [OUTPUT_CAT] = "cat",
+ [OUTPUT_WITH_UNIT] = "with-unit",
};
DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);
diff --git a/src/shared/output-mode.h b/src/shared/output-mode.h
index 747f7eb1b9..fe3903b3c5 100644
--- a/src/shared/output-mode.h
+++ b/src/shared/output-mode.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "macro.h"
typedef enum OutputMode {
@@ -36,6 +17,7 @@ typedef enum OutputMode {
OUTPUT_JSON_PRETTY,
OUTPUT_JSON_SSE,
OUTPUT_CAT,
+ OUTPUT_WITH_UNIT,
_OUTPUT_MODE_MAX,
_OUTPUT_MODE_INVALID = -1
} OutputMode;
diff --git a/src/shared/pager.h b/src/shared/pager.h
deleted file mode 100644
index 99716f8747..0000000000
--- a/src/shared/pager.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-#include "macro.h"
-
-int pager_open(bool no_pager, bool jump_to_end);
-void pager_close(void);
-bool pager_have(void) _pure_;
-
-int show_man_page(const char *page, bool null_stdio);
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
index 5f31831c99..42a5b62d5d 100644
--- a/src/shared/path-lookup.c
+++ b/src/shared/path-lookup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
@@ -181,7 +163,6 @@ static char** user_dirs(
_cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL;
_cleanup_free_ char *data_home = NULL;
_cleanup_strv_free_ char **res = NULL;
- char **tmp;
int r;
r = xdg_user_dirs(&config_dirs, &data_dirs);
@@ -242,10 +223,7 @@ static char** user_dirs(
if (path_strv_make_absolute_cwd(res) < 0)
return NULL;
- tmp = res;
- res = NULL;
-
- return tmp;
+ return TAKE_PTR(res);
}
bool path_is_user_data_dir(const char *path) {
@@ -280,11 +258,10 @@ static int acquire_generator_dirs(
if (tempdir)
prefix = tempdir;
-
else if (scope == UNIT_FILE_SYSTEM)
prefix = "/run/systemd";
-
- else if (scope == UNIT_FILE_USER) {
+ else {
+ /* UNIT_FILE_USER */
const char *e;
e = getenv("XDG_RUNTIME_DIR");
@@ -306,11 +283,10 @@ static int acquire_generator_dirs(
if (!z)
return -ENOMEM;
- *generator = x;
- *generator_early = y;
- *generator_late = z;
+ *generator = TAKE_PTR(x);
+ *generator_early = TAKE_PTR(y);
+ *generator_late = TAKE_PTR(z);
- x = y = z = NULL;
return 0;
}
@@ -374,8 +350,7 @@ static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **ru
*runtime = NULL;
}
- *persistent = a;
- a = NULL;
+ *persistent = TAKE_PTR(a);
return 0;
@@ -386,9 +361,8 @@ static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **ru
if (!a || !b)
return -ENOMEM;
- *persistent = a;
- *runtime = b;
- a = b = NULL;
+ *persistent = TAKE_PTR(a);
+ *runtime = TAKE_PTR(b);
return 0;
}
@@ -413,8 +387,7 @@ static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **r
if (!b)
return -ENOMEM;
- *runtime = b;
- b = NULL;
+ *runtime = TAKE_PTR(b);
break;
}
@@ -443,8 +416,7 @@ static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **r
assert_not_reached("Hmm, unexpected scope value.");
}
- *persistent = a;
- a = NULL;
+ *persistent = TAKE_PTR(a);
return 0;
}
@@ -506,7 +478,11 @@ int lookup_paths_init(
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- if (!isempty(root_dir) && !path_equal(root_dir, "/")) {
+#if HAVE_SPLIT_USR
+ flags |= LOOKUP_PATHS_SPLIT_USR;
+#endif
+
+ if (!empty_or_root(root_dir)) {
if (scope == UNIT_FILE_USER)
return -EINVAL;
@@ -604,9 +580,7 @@ int lookup_paths_init(
"/usr/local/lib/systemd/system",
SYSTEM_DATA_UNIT_PATH,
"/usr/lib/systemd/system",
-#if HAVE_SPLIT_USR
- "/lib/systemd/system",
-#endif
+ STRV_IFNOTNULL(flags & LOOKUP_PATHS_SPLIT_USR ? "/lib/systemd/system" : NULL),
STRV_IFNOTNULL(generator_late),
NULL);
break;
@@ -654,12 +628,10 @@ int lookup_paths_init(
r = strv_extend_strv(&paths, add, true);
if (r < 0)
return r;
- } else {
+ } else
/* Small optimization: if paths is NULL (and it usually is), we can simply assign 'add' to it,
* and don't have to copy anything */
- paths = add;
- add = NULL;
- }
+ paths = TAKE_PTR(add);
}
r = patch_root_prefix(&persistent_config, root);
@@ -698,27 +670,20 @@ int lookup_paths_init(
p->search_path = strv_uniq(paths);
paths = NULL;
- p->persistent_config = persistent_config;
- p->runtime_config = runtime_config;
- persistent_config = runtime_config = NULL;
+ p->persistent_config = TAKE_PTR(persistent_config);
+ p->runtime_config = TAKE_PTR(runtime_config);
- p->generator = generator;
- p->generator_early = generator_early;
- p->generator_late = generator_late;
- generator = generator_early = generator_late = NULL;
+ p->generator = TAKE_PTR(generator);
+ p->generator_early = TAKE_PTR(generator_early);
+ p->generator_late = TAKE_PTR(generator_late);
- p->transient = transient;
- transient = NULL;
+ p->transient = TAKE_PTR(transient);
- p->persistent_control = persistent_control;
- p->runtime_control = runtime_control;
- persistent_control = runtime_control = NULL;
+ p->persistent_control = TAKE_PTR(persistent_control);
+ p->runtime_control = TAKE_PTR(runtime_control);
- p->root_dir = root;
- root = NULL;
-
- p->temporary_dir = tempdir;
- tempdir = NULL;
+ p->root_dir = TAKE_PTR(root);
+ p->temporary_dir = TAKE_PTR(tempdir);
return 0;
}
@@ -748,22 +713,20 @@ void lookup_paths_free(LookupPaths *p) {
int lookup_paths_reduce(LookupPaths *p) {
_cleanup_free_ struct stat *stats = NULL;
size_t n_stats = 0, allocated = 0;
- unsigned c = 0;
+ size_t c = 0;
int r;
assert(p);
/* Drop duplicates and non-existing directories from the search path. We figure out whether two directories are
- * the same by comparing their device and inode numbers. Note one special tweak: when we have a root path set,
- * we do not follow symlinks when retrieving them, because the kernel wouldn't take the root prefix into
- * account when following symlinks. When we have no root path set this restriction does not apply however. */
+ * the same by comparing their device and inode numbers. */
if (!p->search_path)
return 0;
while (p->search_path[c]) {
struct stat st;
- unsigned k;
+ size_t k;
/* Never strip the transient and control directories from the path */
if (path_equal_ptr(p->search_path[c], p->transient) ||
@@ -773,25 +736,20 @@ int lookup_paths_reduce(LookupPaths *p) {
continue;
}
- if (p->root_dir)
- r = lstat(p->search_path[c], &st);
- else
- r = stat(p->search_path[c], &st);
+ r = chase_symlinks_and_stat(p->search_path[c], p->root_dir, 0, NULL, &st);
+ if (r == -ENOENT)
+ goto remove_item;
if (r < 0) {
- if (errno == ENOENT)
- goto remove_item;
-
/* If something we don't grok happened, let's better leave it in. */
- log_debug_errno(errno, "Failed to stat %s: %m", p->search_path[c]);
+ log_debug_errno(r, "Failed to chase and stat %s: %m", p->search_path[c]);
c++;
continue;
}
- for (k = 0; k < n_stats; k++) {
+ for (k = 0; k < n_stats; k++)
if (stats[k].st_dev == st.st_dev &&
stats[k].st_ino == st.st_ino)
break;
- }
if (k < n_stats) /* Is there already an entry with the same device/inode? */
goto remove_item;
@@ -866,14 +824,14 @@ void lookup_paths_flush_generator(LookupPaths *p) {
/* Flush the generated unit files in full */
if (p->generator)
- (void) rm_rf(p->generator, REMOVE_ROOT);
+ (void) rm_rf(p->generator, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->generator_early)
- (void) rm_rf(p->generator_early, REMOVE_ROOT);
+ (void) rm_rf(p->generator_early, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->generator_late)
- (void) rm_rf(p->generator_late, REMOVE_ROOT);
+ (void) rm_rf(p->generator_late, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->temporary_dir)
- (void) rm_rf(p->temporary_dir, REMOVE_ROOT);
+ (void) rm_rf(p->temporary_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
}
char **generator_binary_paths(UnitFileScope scope) {
diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h
index 42a870aa3e..963e09db67 100644
--- a/src/shared/path-lookup.h
+++ b/src/shared/path-lookup.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
typedef struct LookupPaths LookupPaths;
@@ -30,6 +11,7 @@ typedef struct LookupPaths LookupPaths;
typedef enum LookupPathsFlags {
LOOKUP_PATHS_EXCLUDE_GENERATED = 1 << 0,
LOOKUP_PATHS_TEMPORARY_GENERATED = 1 << 1,
+ LOOKUP_PATHS_SPLIT_USR = 1 << 2,
} LookupPathsFlags;
struct LookupPaths {
@@ -82,6 +64,5 @@ void lookup_paths_trim_generator(LookupPaths *p);
void lookup_paths_flush_generator(LookupPaths *p);
void lookup_paths_free(LookupPaths *p);
-#define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free)
char **generator_binary_paths(UnitFileScope scope);
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index 94a4dd513f..c38ec81bbc 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010-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 <limits.h>
@@ -495,8 +477,7 @@ int pty_forward_new(
(void) sd_event_source_set_description(f->sigwinch_event_source, "ptyfwd-sigwinch");
- *ret = f;
- f = NULL;
+ *ret = TAKE_PTR(f);
return 0;
}
diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h
index 6a0e0c6a2b..e4a083ac24 100644
--- a/src/shared/ptyfwd.h
+++ b/src/shared/ptyfwd.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "sd-event.h"
diff --git a/src/shared/resolve-util.c b/src/shared/resolve-util.c
index edcb8e05e7..a5d4a14344 100644
--- a/src/shared/resolve-util.c
+++ b/src/shared/resolve-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "conf-parser.h"
#include "resolve-util.h"
@@ -24,6 +6,7 @@
DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_support, resolve_support, ResolveSupport, "Failed to parse resolve support setting");
DEFINE_CONFIG_PARSE_ENUM(config_parse_dnssec_mode, dnssec_mode, DnssecMode, "Failed to parse DNSSEC mode setting");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_over_tls_mode, dns_over_tls_mode, DnsOverTlsMode, "Failed to parse DNS-over-TLS mode setting");
static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
[RESOLVE_SUPPORT_NO] = "no",
@@ -38,3 +21,9 @@ static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = {
[DNSSEC_YES] = "yes",
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES);
+
+static const char* const dns_over_tls_mode_table[_DNS_OVER_TLS_MODE_MAX] = {
+ [DNS_OVER_TLS_NO] = "no",
+ [DNS_OVER_TLS_OPPORTUNISTIC] = "opportunistic",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_over_tls_mode, DnsOverTlsMode, _DNS_OVER_TLS_MODE_INVALID);
diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h
index 975156ca96..5883342e65 100644
--- a/src/shared/resolve-util.h
+++ b/src/shared/resolve-util.h
@@ -1,29 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
+#include "conf-parser.h"
#include "macro.h"
typedef enum ResolveSupport ResolveSupport;
typedef enum DnssecMode DnssecMode;
+typedef enum DnsOverTlsMode DnsOverTlsMode;
enum ResolveSupport {
RESOLVE_SUPPORT_NO,
@@ -51,11 +34,27 @@ enum DnssecMode {
_DNSSEC_MODE_INVALID = -1
};
-int config_parse_resolve_support(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssec_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+enum DnsOverTlsMode {
+ /* No connection is made for DNS-over-TLS */
+ DNS_OVER_TLS_NO,
+
+ /* Try to connect using DNS-over-TLS, but if connection fails,
+ * fallback to using an unencrypted connection */
+ DNS_OVER_TLS_OPPORTUNISTIC,
+
+ _DNS_OVER_TLS_MODE_MAX,
+ _DNS_OVER_TLS_MODE_INVALID = -1
+};
+
+CONFIG_PARSER_PROTOTYPE(config_parse_resolve_support);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns_over_tls_mode);
const char* resolve_support_to_string(ResolveSupport p) _const_;
ResolveSupport resolve_support_from_string(const char *s) _pure_;
const char* dnssec_mode_to_string(DnssecMode p) _const_;
DnssecMode dnssec_mode_from_string(const char *s) _pure_;
+
+const char* dns_over_tls_mode_to_string(DnsOverTlsMode p) _const_;
+DnsOverTlsMode dns_over_tls_mode_from_string(const char *s) _pure_;
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 220658b3ad..c433cb90dc 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <linux/seccomp.h>
@@ -650,7 +632,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
"setresuid32\0"
"setreuid\0"
"setreuid32\0"
- "setuid\0"
+ "setuid\0" /* We list the explicit system calls here, as @setuid also includes setgid() which is not necessarily privileged */
"setuid32\0"
"vhangup\0"
},
@@ -774,6 +756,75 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
"sync_file_range\0"
"syncfs\0"
},
+ [SYSCALL_FILTER_SET_SYSTEM_SERVICE] = {
+ .name = "@system-service",
+ .help = "General system service operations",
+ .value =
+ "@aio\0"
+ "@basic-io\0"
+ "@chown\0"
+ "@default\0"
+ "@file-system\0"
+ "@io-event\0"
+ "@ipc\0"
+ "@keyring\0"
+ "@memlock\0"
+ "@network-io\0"
+ "@process\0"
+ "@resources\0"
+ "@setuid\0"
+ "@signal\0"
+ "@sync\0"
+ "@timer\0"
+ "brk\0"
+ "capget\0"
+ "capset\0"
+ "copy_file_range\0"
+ "fadvise64\0"
+ "fadvise64_64\0"
+ "flock\0"
+ "get_mempolicy\0"
+ "getcpu\0"
+ "getpriority\0"
+ "getrandom\0"
+ "ioctl\0"
+ "ioprio_get\0"
+ "kcmp\0"
+ "madvise\0"
+ "mincore\0"
+ "mprotect\0"
+ "mremap\0"
+ "name_to_handle_at\0"
+ "oldolduname\0"
+ "olduname\0"
+ "personality\0"
+ "readahead\0"
+ "readdir\0"
+ "remap_file_pages\0"
+ "sched_get_priority_max\0"
+ "sched_get_priority_min\0"
+ "sched_getaffinity\0"
+ "sched_getattr\0"
+ "sched_getparam\0"
+ "sched_getscheduler\0"
+ "sched_rr_get_interval\0"
+ "sched_yield\0"
+ "sendfile\0"
+ "sendfile64\0"
+ "setfsgid\0"
+ "setfsgid32\0"
+ "setfsuid\0"
+ "setfsuid32\0"
+ "setpgid\0"
+ "setsid\0"
+ "splice\0"
+ "sysinfo\0"
+ "tee\0"
+ "umask\0"
+ "uname\0"
+ "userfaultfd\0"
+ "vmsplice\0"
+ },
[SYSCALL_FILTER_SET_TIMER] = {
.name = "@timer",
.help = "Schedule operations by time",
@@ -1020,7 +1071,7 @@ int seccomp_restrict_namespaces(unsigned long retain) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *s = NULL;
- (void) namespace_flag_to_string_many(retain, &s);
+ (void) namespace_flags_to_string(retain, &s);
log_debug("Restricting namespace to: %s.", strna(s));
}
@@ -1182,16 +1233,22 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
case SCMP_ARCH_X32:
case SCMP_ARCH_ARM:
case SCMP_ARCH_AARCH64:
+ case SCMP_ARCH_PPC:
case SCMP_ARCH_PPC64:
case SCMP_ARCH_PPC64LE:
+ case SCMP_ARCH_MIPSEL64N32:
+ case SCMP_ARCH_MIPS64N32:
+ case SCMP_ARCH_MIPSEL64:
+ case SCMP_ARCH_MIPS64:
/* These we know we support (i.e. are the ones that do not use socketcall()) */
supported = true;
break;
case SCMP_ARCH_S390:
case SCMP_ARCH_S390X:
- case SCMP_ARCH_PPC:
case SCMP_ARCH_X86:
+ case SCMP_ARCH_MIPSEL:
+ case SCMP_ARCH_MIPS:
default:
/* These we either know we don't support (i.e. are the ones that do use socketcall()), or we
* don't know */
@@ -1607,8 +1664,7 @@ int parse_syscall_archs(char **l, Set **archs) {
return -ENOMEM;
}
- *archs = _archs;
- _archs = NULL;
+ *archs = TAKE_PTR(_archs);
return 0;
}
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
index 5915ceb9a3..eac857afb9 100644
--- a/src/shared/seccomp-util.h
+++ b/src/shared/seccomp-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <seccomp.h>
#include <stdbool.h>
#include <stdint.h>
@@ -66,6 +47,7 @@ enum {
SYSCALL_FILTER_SET_SIGNAL,
SYSCALL_FILTER_SET_SWAP,
SYSCALL_FILTER_SET_SYNC,
+ SYSCALL_FILTER_SET_SYSTEM_SERVICE,
SYSCALL_FILTER_SET_TIMER,
_SYSCALL_FILTER_SET_MAX
};
@@ -82,10 +64,10 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action);
typedef enum SeccompParseFlags {
- SECCOMP_PARSE_INVERT = 1U << 0,
- SECCOMP_PARSE_WHITELIST = 1U << 1,
- SECCOMP_PARSE_LOG = 1U << 2,
- SECCOMP_PARSE_PERMISSIVE = 1U << 3,
+ SECCOMP_PARSE_INVERT = 1 << 0,
+ SECCOMP_PARSE_WHITELIST = 1 << 1,
+ SECCOMP_PARSE_LOG = 1 << 2,
+ SECCOMP_PARSE_PERMISSIVE = 1 << 3,
} SeccompParseFlags;
int seccomp_parse_syscall_filter_full(
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index ecac98e0ab..9e4ce183d3 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -1,24 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2018 Dell Inc.
***/
#include <errno.h>
+#include <linux/fs.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
@@ -39,15 +25,14 @@
#include "string-util.h"
#include "strv.h"
-#define USE(x, y) do { (x) = (y); (y) = NULL; } while (0)
-
-int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
+int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t *_delay) {
_cleanup_strv_free_ char
**suspend_mode = NULL, **suspend_state = NULL,
**hibernate_mode = NULL, **hibernate_state = NULL,
**hybrid_mode = NULL, **hybrid_state = NULL;
- char **modes, **states;
+ _cleanup_strv_free_ char **modes, **states; /* always initialized below */
+ usec_t delay = 180 * USEC_PER_MINUTE;
const ConfigTableItem items[] = {
{ "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode },
@@ -56,6 +41,7 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
{ "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state },
{ "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode },
{ "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state },
+ { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &delay},
{}
};
@@ -66,46 +52,51 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
if (streq(verb, "suspend")) {
/* empty by default */
- USE(modes, suspend_mode);
+ modes = TAKE_PTR(suspend_mode);
if (suspend_state)
- USE(states, suspend_state);
+ states = TAKE_PTR(suspend_state);
else
states = strv_new("mem", "standby", "freeze", NULL);
} else if (streq(verb, "hibernate")) {
if (hibernate_mode)
- USE(modes, hibernate_mode);
+ modes = TAKE_PTR(hibernate_mode);
else
modes = strv_new("platform", "shutdown", NULL);
if (hibernate_state)
- USE(states, hibernate_state);
+ states = TAKE_PTR(hibernate_state);
else
states = strv_new("disk", NULL);
} else if (streq(verb, "hybrid-sleep")) {
if (hybrid_mode)
- USE(modes, hybrid_mode);
+ modes = TAKE_PTR(hybrid_mode);
else
modes = strv_new("suspend", "platform", "shutdown", NULL);
if (hybrid_state)
- USE(states, hybrid_state);
+ states = TAKE_PTR(hybrid_state);
else
states = strv_new("disk", NULL);
- } else
+ } else if (streq(verb, "suspend-then-hibernate"))
+ modes = states = NULL;
+ else
assert_not_reached("what verb");
- if ((!modes && !streq(verb, "suspend")) || !states) {
- strv_free(modes);
- strv_free(states);
+ if ((!modes && STR_IN_SET(verb, "hibernate", "hybrid-sleep")) ||
+ (!states && !streq(verb, "suspend-then-hibernate")))
return log_oom();
- }
- *_modes = modes;
- *_states = states;
+ if (_modes)
+ *_modes = TAKE_PTR(modes);
+ if (_states)
+ *_states = TAKE_PTR(states);
+ if (_delay)
+ *_delay = delay;
+
return 0;
}
@@ -176,13 +167,10 @@ int can_sleep_disk(char **types) {
#define HIBERNATION_SWAP_THRESHOLD 0.98
-static int hibernation_partition_size(size_t *size, size_t *used) {
+int find_hibernate_location(char **device, char **type, size_t *size, size_t *used) {
_cleanup_fclose_ FILE *f;
unsigned i;
- assert(size);
- assert(used);
-
f = fopen("/proc/swaps", "re");
if (!f) {
log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
@@ -194,7 +182,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
(void) fscanf(f, "%*s %*s %*s %*s %*s\n");
for (i = 1;; i++) {
- _cleanup_free_ char *dev = NULL, *type = NULL;
+ _cleanup_free_ char *dev_field = NULL, *type_field = NULL;
size_t size_field, used_field;
int k;
@@ -204,7 +192,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
"%zu " /* swap size */
"%zu " /* used */
"%*i\n", /* priority */
- &dev, &type, &size_field, &used_field);
+ &dev_field, &type_field, &size_field, &used_field);
if (k != 4) {
if (k == EOF)
break;
@@ -213,13 +201,18 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
continue;
}
- if (streq(type, "partition") && endswith(dev, "\\040(deleted)")) {
- log_warning("Ignoring deleted swapfile '%s'.", dev);
+ if (streq(type_field, "partition") && endswith(dev_field, "\\040(deleted)")) {
+ log_warning("Ignoring deleted swapfile '%s'.", dev_field);
continue;
}
-
- *size = size_field;
- *used = used_field;
+ if (device)
+ *device = TAKE_PTR(dev_field);
+ if (type)
+ *type = TAKE_PTR(type_field);
+ if (size)
+ *size = size_field;
+ if (used)
+ *used = used_field;
return 0;
}
@@ -227,7 +220,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
return -ENOSYS;
}
-static bool enough_memory_for_hibernation(void) {
+static bool enough_swap_for_hibernation(void) {
_cleanup_free_ char *active = NULL;
unsigned long long act = 0;
size_t size = 0, used = 0;
@@ -236,7 +229,7 @@ static bool enough_memory_for_hibernation(void) {
if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0)
return true;
- r = hibernation_partition_size(&size, &used);
+ r = find_hibernate_location(NULL, NULL, &size, &used);
if (r < 0)
return false;
@@ -260,20 +253,135 @@ static bool enough_memory_for_hibernation(void) {
return r;
}
+int read_fiemap(int fd, struct fiemap **ret) {
+ _cleanup_free_ struct fiemap *fiemap = NULL, *result_fiemap = NULL;
+ struct stat statinfo;
+ uint32_t result_extents = 0;
+ uint64_t fiemap_start = 0, fiemap_length;
+ const size_t n_extra = DIV_ROUND_UP(sizeof(struct fiemap), sizeof(struct fiemap_extent));
+ size_t fiemap_allocated = n_extra, result_fiemap_allocated = n_extra;
+
+ if (fstat(fd, &statinfo) < 0)
+ return log_debug_errno(errno, "Cannot determine file size: %m");
+ if (!S_ISREG(statinfo.st_mode))
+ return -ENOTTY;
+ fiemap_length = statinfo.st_size;
+
+ /* Zero this out in case we run on a file with no extents */
+ fiemap = calloc(n_extra, sizeof(struct fiemap_extent));
+ if (!fiemap)
+ return -ENOMEM;
+
+ result_fiemap = malloc_multiply(n_extra, sizeof(struct fiemap_extent));
+ if (!result_fiemap)
+ return -ENOMEM;
+
+ /* XFS filesystem has incorrect implementation of fiemap ioctl and
+ * returns extents for only one block-group at a time, so we need
+ * to handle it manually, starting the next fiemap call from the end
+ * of the last extent
+ */
+ while (fiemap_start < fiemap_length) {
+ *fiemap = (struct fiemap) {
+ .fm_start = fiemap_start,
+ .fm_length = fiemap_length,
+ .fm_flags = FIEMAP_FLAG_SYNC,
+ };
+
+ /* Find out how many extents there are */
+ if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
+ return log_debug_errno(errno, "Failed to read extents: %m");
+
+ /* Nothing to process */
+ if (fiemap->fm_mapped_extents == 0)
+ break;
+
+ /* Resize fiemap to allow us to read in the extents, result fiemap has to hold all
+ * the extents for the whole file. Add space for the initial struct fiemap. */
+ if (!greedy_realloc0((void**) &fiemap, &fiemap_allocated,
+ n_extra + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
+ return -ENOMEM;
+
+ fiemap->fm_extent_count = fiemap->fm_mapped_extents;
+ fiemap->fm_mapped_extents = 0;
+
+ if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
+ return log_debug_errno(errno, "Failed to read extents: %m");
+
+ /* Resize result_fiemap to allow us to copy in the extents */
+ if (!greedy_realloc((void**) &result_fiemap, &result_fiemap_allocated,
+ n_extra + result_extents + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
+ return -ENOMEM;
+
+ memcpy(result_fiemap->fm_extents + result_extents,
+ fiemap->fm_extents,
+ sizeof(struct fiemap_extent) * fiemap->fm_mapped_extents);
+
+ result_extents += fiemap->fm_mapped_extents;
+
+ /* Highly unlikely that it is zero */
+ if (_likely_(fiemap->fm_mapped_extents > 0)) {
+ uint32_t i = fiemap->fm_mapped_extents - 1;
+
+ fiemap_start = fiemap->fm_extents[i].fe_logical +
+ fiemap->fm_extents[i].fe_length;
+
+ if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST)
+ break;
+ }
+ }
+
+ memcpy(result_fiemap, fiemap, sizeof(struct fiemap));
+ result_fiemap->fm_mapped_extents = result_extents;
+ *ret = TAKE_PTR(result_fiemap);
+ return 0;
+}
+
+static bool can_s2h(void) {
+ const char *p;
+ int r;
+
+ r = access("/sys/class/rtc/rtc0/wakealarm", W_OK);
+ if (r < 0) {
+ log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+ "/sys/class/rct/rct0/wakealarm is not writable %m");
+ return false;
+ }
+
+ FOREACH_STRING(p, "suspend", "hibernate") {
+ r = can_sleep(p);
+ if (IN_SET(r, 0, -ENOSPC)) {
+ log_debug("Unable to %s system.", p);
+ return false;
+ }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to check if %s is possible: %m", p);
+ }
+
+ return true;
+}
+
int can_sleep(const char *verb) {
_cleanup_strv_free_ char **modes = NULL, **states = NULL;
int r;
- assert(streq(verb, "suspend") ||
- streq(verb, "hibernate") ||
- streq(verb, "hybrid-sleep"));
+ assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate"));
- r = parse_sleep_config(verb, &modes, &states);
+ if (streq(verb, "suspend-then-hibernate"))
+ return can_s2h();
+
+ r = parse_sleep_config(verb, &modes, &states, NULL);
if (r < 0)
return false;
if (!can_sleep_state(states) || !can_sleep_disk(modes))
return false;
- return streq(verb, "suspend") || enough_memory_for_hibernation();
+ if (streq(verb, "suspend"))
+ return true;
+
+ if (!enough_swap_for_hibernation())
+ return -ENOSPC;
+
+ return true;
}
diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h
index fc5a81d954..6bf035969a 100644
--- a/src/shared/sleep-config.h
+++ b/src/shared/sleep-config.h
@@ -1,26 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
+#include <linux/fiemap.h>
+#include "time-util.h"
- 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/>.
-***/
-
-int parse_sleep_config(const char *verb, char ***modes, char ***states);
+int read_fiemap(int fd, struct fiemap **ret);
+int parse_sleep_config(const char *verb, char ***modes, char ***states, usec_t *delay);
+int find_hibernate_location(char **device, char **type, size_t *size, size_t *used);
int can_sleep(const char *verb);
int can_sleep_disk(char **types);
diff --git a/src/shared/spawn-ask-password-agent.c b/src/shared/spawn-ask-password-agent.c
index f78167c25c..309071c89d 100644
--- a/src/shared/spawn-ask-password-agent.c
+++ b/src/shared/spawn-ask-password-agent.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <signal.h>
#include <stdlib.h>
diff --git a/src/shared/spawn-ask-password-agent.h b/src/shared/spawn-ask-password-agent.h
index 158f8839ab..97e73bda44 100644
--- a/src/shared/spawn-ask-password-agent.h
+++ b/src/shared/spawn-ask-password-agent.h
@@ -1,24 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
int ask_password_agent_open(void);
void ask_password_agent_close(void);
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index 3c93c79ceb..180cb7964c 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <poll.h>
diff --git a/src/shared/spawn-polkit-agent.h b/src/shared/spawn-polkit-agent.h
index 9f26fa10a7..190b970b6f 100644
--- a/src/shared/spawn-polkit-agent.h
+++ b/src/shared/spawn-polkit-agent.h
@@ -1,41 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "bus-util.h"
int polkit_agent_open(void);
void polkit_agent_close(void);
-static inline void polkit_agent_open_if_enabled(
+static inline int polkit_agent_open_if_enabled(
BusTransport transport,
bool ask_password) {
/* Open the polkit agent as a child process if necessary */
if (transport != BUS_TRANSPORT_LOCAL)
- return;
+ return 0;
if (!ask_password)
- return;
+ return 0;
- polkit_agent_open();
+ return polkit_agent_open();
}
diff --git a/src/shared/specifier.c b/src/shared/specifier.c
index 849ff67e76..d698b42e07 100644
--- a/src/shared/specifier.c
+++ b/src/shared/specifier.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdbool.h>
@@ -28,6 +10,7 @@
#include "sd-id128.h"
#include "alloc-util.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "macro.h"
#include "specifier.h"
@@ -114,8 +97,7 @@ int specifier_printf(const char *text, const Specifier table[], void *userdata,
ret = t;
}
- *_ret = ret;
- ret = NULL;
+ *_ret = TAKE_PTR(ret);
return 0;
}
@@ -236,6 +218,40 @@ int specifier_user_shell(char specifier, void *data, void *userdata, char **ret)
return get_shell(ret);
}
+int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret) {
+ const char *p;
+ char *copy;
+ int r;
+
+ r = tmp_dir(&p);
+ if (r < 0)
+ return r;
+
+ copy = strdup(p);
+ if (!copy)
+ return -ENOMEM;
+
+ *ret = copy;
+ return 0;
+}
+
+int specifier_var_tmp_dir(char specifier, void *data, void *userdata, char **ret) {
+ const char *p;
+ char *copy;
+ int r;
+
+ r = var_tmp_dir(&p);
+ if (r < 0)
+ return r;
+
+ copy = strdup(p);
+ if (!copy)
+ return -ENOMEM;
+
+ *ret = copy;
+ return 0;
+}
+
int specifier_escape_strv(char **l, char ***ret) {
char **z, **p, **q;
diff --git a/src/shared/specifier.h b/src/shared/specifier.h
index bd6bc55577..e1895129d7 100644
--- a/src/shared/specifier.h
+++ b/src/shared/specifier.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "string-util.h"
typedef int (*SpecifierCallback)(char specifier, void *data, void *userdata, char **ret);
@@ -44,6 +25,9 @@ int specifier_user_id(char specifier, void *data, void *userdata, char **ret);
int specifier_user_home(char specifier, void *data, void *userdata, char **ret);
int specifier_user_shell(char specifier, void *data, void *userdata, char **ret);
+int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret);
+int specifier_var_tmp_dir(char specifier, void *data, void *userdata, char **ret);
+
static inline char* specifier_escape(const char *string) {
return strreplace(string, "%", "%%");
}
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index 3c51fa36f3..28740cb474 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2012 Harald Hoyer, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Harald Hoyer
***/
#include <errno.h>
diff --git a/src/shared/switch-root.h b/src/shared/switch-root.h
index abcdc1c65f..83294a4525 100644
--- a/src/shared/switch-root.h
+++ b/src/shared/switch-root.h
@@ -1,24 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-#include <stdbool.h>
/***
- This file is part of systemd.
-
- Copyright 2012 Harald Hoyer, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Harald Hoyer
***/
+#include <stdbool.h>
+
int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, unsigned long mountflags);
diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c
index 0bc81aaa56..326652273c 100644
--- a/src/shared/sysctl-util.c
+++ b/src/shared/sysctl-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/shared/sysctl-util.h b/src/shared/sysctl-util.h
index 446aa6f384..fd7c78b2b8 100644
--- a/src/shared/sysctl-util.h
+++ b/src/shared/sysctl-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
char *sysctl_normalize(char *s);
int sysctl_read(const char *property, char **value);
int sysctl_write(const char *property, const char *value);
diff --git a/src/shared/test-tables.h b/src/shared/test-tables.h
index dd8bf0b582..4eeda3b1bb 100644
--- a/src/shared/test-tables.h
+++ b/src/shared/test-tables.h
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
#include <stdlib.h>
diff --git a/src/shared/tests.c b/src/shared/tests.c
index d4781acabf..6b3df0aa07 100644
--- a/src/shared/tests.c
+++ b/src/shared/tests.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <alloc-util.h>
#include <fs-util.h>
diff --git a/src/shared/tests.h b/src/shared/tests.h
index b070f386e3..b88135ed93 100644
--- a/src/shared/tests.h
+++ b/src/shared/tests.h
@@ -1,24 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
char* setup_fake_runtime_dir(void);
const char* get_testdata_dir(const char *suffix);
diff --git a/src/shared/tomoyo-util.c b/src/shared/tomoyo-util.c
index 390fff6152..75c24d8007 100644
--- a/src/shared/tomoyo-util.c
+++ b/src/shared/tomoyo-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Shawn Landden
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
diff --git a/src/shared/tomoyo-util.h b/src/shared/tomoyo-util.h
index 4fb309fd54..03e6975469 100644
--- a/src/shared/tomoyo-util.h
+++ b/src/shared/tomoyo-util.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2017 Shawn Landden
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c
index 65a09e9c2e..16a0eed841 100644
--- a/src/shared/udev-util.c
+++ b/src/shared/udev-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
@@ -31,7 +13,7 @@ int udev_parse_config(void) {
size_t n;
int r;
- r = parse_env_file("/etc/udev/udev.conf", NEWLINE, "udev_log", &val, NULL);
+ r = parse_env_file(NULL, "/etc/udev/udev.conf", NEWLINE, "udev_log", &val, NULL);
if (r == -ENOENT || !val)
return 0;
if (r < 0)
@@ -55,3 +37,26 @@ int udev_parse_config(void) {
return 0;
}
+
+int udev_device_new_from_stat_rdev(struct udev *udev, const struct stat *st, struct udev_device **ret) {
+ struct udev_device *nd;
+ char type;
+
+ assert(udev);
+ assert(st);
+ assert(ret);
+
+ if (S_ISBLK(st->st_mode))
+ type = 'b';
+ else if (S_ISCHR(st->st_mode))
+ type = 'c';
+ else
+ return -ENOTTY;
+
+ nd = udev_device_new_from_devnum(udev, type, st->st_rdev);
+ if (!nd)
+ return -errno;
+
+ *ret = nd;
+ return 0;
+}
diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h
index c5e4197dff..f36c568b5a 100644
--- a/src/shared/udev-util.h
+++ b/src/shared/udev-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "udev.h"
#include "util.h"
@@ -33,15 +14,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_connection*, udev_ctrl_connection_u
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_msg*, udev_ctrl_msg_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_monitor*, udev_monitor_unref);
-#define _cleanup_udev_unref_ _cleanup_(udev_unrefp)
-#define _cleanup_udev_device_unref_ _cleanup_(udev_device_unrefp)
-#define _cleanup_udev_enumerate_unref_ _cleanup_(udev_enumerate_unrefp)
-#define _cleanup_udev_event_unref_ _cleanup_(udev_event_unrefp)
-#define _cleanup_udev_rules_unref_ _cleanup_(udev_rules_unrefp)
-#define _cleanup_udev_ctrl_unref_ _cleanup_(udev_ctrl_unrefp)
-#define _cleanup_udev_ctrl_connection_unref_ _cleanup_(udev_ctrl_connection_unrefp)
-#define _cleanup_udev_ctrl_msg_unref_ _cleanup_(udev_ctrl_msg_unrefp)
-#define _cleanup_udev_monitor_unref_ _cleanup_(udev_monitor_unrefp)
-#define _cleanup_udev_list_cleanup_ _cleanup_(udev_list_cleanup)
-
int udev_parse_config(void);
+
+int udev_device_new_from_stat_rdev(struct udev *udev, const struct stat *st, struct udev_device **ret);
diff --git a/src/shared/uid-range.c b/src/shared/uid-range.c
index 37d7c981f2..434ce6ff4d 100644
--- a/src/shared/uid-range.c
+++ b/src/shared/uid-range.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
@@ -61,7 +43,6 @@ static void uid_range_coalesce(UidRange **p, unsigned *n) {
}
}
}
-
}
static int uid_range_compare(const void *a, const void *b) {
diff --git a/src/shared/uid-range.h b/src/shared/uid-range.h
index 882f6624cd..49ba38287e 100644
--- a/src/shared/uid-range.h
+++ b/src/shared/uid-range.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c
index cab1cd6a2d..ef9427fa7b 100644
--- a/src/shared/utmp-wtmp.c
+++ b/src/shared/utmp-wtmp.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -288,7 +270,6 @@ int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
return write_utmp_wtmp(&store, &store_wtmp);
}
-
int utmp_put_runlevel(int runlevel, int previous) {
struct utmpx store = {};
int r;
diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h
index 2c75d4097e..9e433cf73e 100644
--- a/src/shared/utmp-wtmp.h
+++ b/src/shared/utmp-wtmp.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
diff --git a/src/shared/vlan-util.c b/src/shared/vlan-util.c
index fa270164bb..400994a354 100644
--- a/src/shared/vlan-util.c
+++ b/src/shared/vlan-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "conf-parser.h"
#include "parse-util.h"
diff --git a/src/shared/vlan-util.h b/src/shared/vlan-util.h
index 6d287fd32a..ebe4331ed4 100644
--- a/src/shared/vlan-util.h
+++ b/src/shared/vlan-util.h
@@ -1,28 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <inttypes.h>
+#include "conf-parser.h"
+
#define VLANID_MAX 4094
#define VLANID_INVALID UINT16_MAX
@@ -33,5 +16,5 @@ static inline bool vlanid_is_valid(uint16_t id) {
int parse_vlanid(const char *p, uint16_t *ret);
-int config_parse_default_port_vlanid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_vlanid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_default_port_vlanid);
+CONFIG_PARSER_PROTOTYPE(config_parse_vlanid);
diff --git a/src/shared/volatile-util.c b/src/shared/volatile-util.c
index c92ad0adc0..4d75bc0e96 100644
--- a/src/shared/volatile-util.c
+++ b/src/shared/volatile-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
@@ -24,27 +6,10 @@
#include "macro.h"
#include "parse-util.h"
#include "proc-cmdline.h"
+#include "string-table.h"
#include "string-util.h"
#include "volatile-util.h"
-VolatileMode volatile_mode_from_string(const char *s) {
- int b;
-
- if (isempty(s))
- return _VOLATILE_MODE_INVALID;
-
- b = parse_boolean(s);
- if (b > 0)
- return VOLATILE_YES;
- if (b == 0)
- return VOLATILE_NO;
-
- if (streq(s, "state"))
- return VOLATILE_STATE;
-
- return _VOLATILE_MODE_INVALID;
-}
-
int query_volatile_mode(VolatileMode *ret) {
_cleanup_free_ char *mode = NULL;
VolatileMode m = VOLATILE_NO;
@@ -69,3 +34,11 @@ finish:
*ret = m;
return r;
}
+
+static const char* const volatile_mode_table[_VOLATILE_MODE_MAX] = {
+ [VOLATILE_NO] = "no",
+ [VOLATILE_YES] = "yes",
+ [VOLATILE_STATE] = "state",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(volatile_mode, VolatileMode, VOLATILE_YES);
diff --git a/src/shared/volatile-util.h b/src/shared/volatile-util.h
index 3ad037af8b..8761c44ab8 100644
--- a/src/shared/volatile-util.h
+++ b/src/shared/volatile-util.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
typedef enum VolatileMode {
VOLATILE_NO,
VOLATILE_YES,
@@ -29,5 +10,6 @@ typedef enum VolatileMode {
} VolatileMode;
VolatileMode volatile_mode_from_string(const char *s);
+const char* volatile_mode_to_string(VolatileMode m);
int query_volatile_mode(VolatileMode *ret);
diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c
index b0a422da84..c423af6917 100644
--- a/src/shared/watchdog.c
+++ b/src/shared/watchdog.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
@@ -54,7 +36,7 @@ static int update_timeout(void) {
int sec, flags;
char buf[FORMAT_TIMESPAN_MAX];
- sec = (int) ((watchdog_timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
+ sec = (int) DIV_ROUND_UP(watchdog_timeout, USEC_PER_SEC);
r = ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec);
if (r < 0)
return log_warning_errno(errno, "Failed to set timeout to %is: %m", sec);
diff --git a/src/shared/watchdog.h b/src/shared/watchdog.h
index 5694338db3..a345e4ba7d 100644
--- a/src/shared/watchdog.h
+++ b/src/shared/watchdog.h
@@ -1,25 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "time-util.h"
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 518032ec69..f26aa453c9 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -1,42 +1,91 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010-2017 Canonical
+ Copyright © 2018 Dell Inc.
***/
#include <errno.h>
#include <getopt.h>
+#include <linux/fiemap.h>
#include <stdio.h>
#include "sd-messages.h"
+#include "parse-util.h"
#include "def.h"
#include "exec-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "sleep-config.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
static char* arg_verb = NULL;
+static int write_hibernate_location_info(void) {
+ _cleanup_free_ char *device = NULL, *type = NULL;
+ _cleanup_free_ struct fiemap *fiemap = NULL;
+ char offset_str[DECIMAL_STR_MAX(uint64_t)];
+ char device_str[DECIMAL_STR_MAX(uint64_t)];
+ _cleanup_close_ int fd = -1;
+ struct stat stb;
+ uint64_t offset;
+ int r;
+
+ r = find_hibernate_location(&device, &type, NULL, NULL);
+ if (r < 0)
+ return log_debug_errno(r, "Unable to find hibernation location: %m");
+
+ /* if it's a swap partition, we just write the disk to /sys/power/resume */
+ if (streq(type, "partition"))
+ return write_string_file("/sys/power/resume", device, 0);
+ else if (!streq(type, "file"))
+ return log_debug_errno(EINVAL, "Invalid hibernate type %s: %m",
+ type);
+
+ /* Only available in 4.17+ */
+ if (access("/sys/power/resume_offset", F_OK) < 0) {
+ if (errno == ENOENT)
+ return 0;
+ return log_debug_errno(errno, "/sys/power/resume_offset unavailable: %m");
+ }
+
+ r = access("/sys/power/resume_offset", W_OK);
+ if (r < 0)
+ return log_debug_errno(errno, "/sys/power/resume_offset not writeable: %m");
+
+ fd = open(device, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
+ if (fd < 0)
+ return log_debug_errno(errno, "Unable to open '%s': %m", device);
+ r = fstat(fd, &stb);
+ if (r < 0)
+ return log_debug_errno(errno, "Unable to stat %s: %m", device);
+ r = read_fiemap(fd, &fiemap);
+ if (r < 0)
+ return log_debug_errno(r, "Unable to read extent map for '%s': %m",
+ device);
+ if (fiemap->fm_mapped_extents == 0) {
+ log_debug("No extents found in '%s'", device);
+ return -EINVAL;
+ }
+ offset = fiemap->fm_extents[0].fe_physical / page_size();
+ xsprintf(offset_str, "%" PRIu64, offset);
+ r = write_string_file("/sys/power/resume_offset", offset_str, 0);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to write offset '%s': %m",
+ offset_str);
+
+ xsprintf(device_str, "%lx", (unsigned long)stb.st_dev);
+ r = write_string_file("/sys/power/resume", device_str, 0);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to write device '%s': %m",
+ device_str);
+ return 0;
+}
+
static int write_mode(char **modes) {
int r = 0;
char **mode;
@@ -54,9 +103,6 @@ static int write_mode(char **modes) {
r = k;
}
- if (r < 0)
- log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");
-
return r;
}
@@ -78,7 +124,7 @@ static int write_state(FILE **f, char **states) {
fclose(*f);
*f = fopen("/sys/power/state", "we");
if (!*f)
- return log_error_errno(errno, "Failed to open /sys/power/state: %m");
+ return -errno;
}
return r;
@@ -107,27 +153,30 @@ static int execute(char **modes, char **states) {
return log_error_errno(errno, "Failed to open /sys/power/state: %m");
/* Configure the hibernation mode */
- r = write_mode(modes);
- if (r < 0)
- return r;
+ if (!strv_isempty(modes)) {
+ r = write_hibernate_location_info();
+ if (r < 0)
+ return log_error_errno(r, "Failed to write hibernation disk offset: %m");
+ r = write_mode(modes);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;
+ }
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
LOG_MESSAGE("Suspending system..."),
- "SLEEP=%s", arg_verb,
- NULL);
+ "SLEEP=%s", arg_verb);
r = write_state(&f, states);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to write /sys/power/state: %m");
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
LOG_MESSAGE("System resumed."),
- "SLEEP=%s", arg_verb,
- NULL);
+ "SLEEP=%s", arg_verb);
arguments[1] = (char*) "post";
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
@@ -135,6 +184,83 @@ static int execute(char **modes, char **states) {
return r;
}
+static int read_wakealarm(uint64_t *result) {
+ _cleanup_free_ char *t = NULL;
+
+ if (read_one_line_file("/sys/class/rtc/rtc0/since_epoch", &t) >= 0)
+ return safe_atou64(t, result);
+ return -EBADF;
+}
+
+static int write_wakealarm(const char *str) {
+
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ f = fopen("/sys/class/rtc/rtc0/wakealarm", "we");
+ if (!f)
+ return log_error_errno(errno, "Failed to open /sys/class/rtc/rtc0/wakealarm: %m");
+
+ r = write_string_stream(f, str, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write '%s' to /sys/class/rtc/rtc0/wakealarm: %m", str);
+
+ return 0;
+}
+
+static int execute_s2h(usec_t hibernate_delay_sec) {
+
+ _cleanup_strv_free_ char **hibernate_modes = NULL, **hibernate_states = NULL,
+ **suspend_modes = NULL, **suspend_states = NULL;
+ usec_t orig_time, cmp_time;
+ char time_str[DECIMAL_STR_MAX(uint64_t)];
+ int r;
+
+ r = parse_sleep_config("suspend", &suspend_modes, &suspend_states,
+ NULL);
+ if (r < 0)
+ return r;
+
+ r = parse_sleep_config("hibernate", &hibernate_modes,
+ &hibernate_states, NULL);
+ if (r < 0)
+ return r;
+
+ r = read_wakealarm(&orig_time);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to read time: %d", r);
+
+ orig_time += hibernate_delay_sec / USEC_PER_SEC;
+ xsprintf(time_str, "%" PRIu64, orig_time);
+
+ r = write_wakealarm(time_str);
+ if (r < 0)
+ return r;
+
+ log_debug("Set RTC wake alarm for %s", time_str);
+
+ r = execute(suspend_modes, suspend_states);
+ if (r < 0)
+ return r;
+
+ r = read_wakealarm(&cmp_time);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to read time: %d", r);
+
+ /* reset RTC */
+ r = write_wakealarm("0");
+ if (r < 0)
+ return r;
+
+ log_debug("Woke up at %"PRIu64, cmp_time);
+
+ /* if woken up after alarm time, hibernate */
+ if (cmp_time >= orig_time)
+ r = execute(hibernate_modes, hibernate_states);
+
+ return r;
+}
+
static void help(void) {
printf("%s COMMAND\n\n"
"Suspend the system, hibernate the system, or both.\n\n"
@@ -144,6 +270,8 @@ static void help(void) {
" suspend Suspend the system\n"
" hibernate Hibernate the system\n"
" hybrid-sleep Both hibernate and suspend the system\n"
+ " suspend-then-hibernate Initially suspend and then hibernate\n"
+ " the system after a fixed period of time\n"
, program_invocation_short_name);
}
@@ -189,7 +317,8 @@ static int parse_argv(int argc, char *argv[]) {
if (!streq(arg_verb, "suspend") &&
!streq(arg_verb, "hibernate") &&
- !streq(arg_verb, "hybrid-sleep")) {
+ !streq(arg_verb, "hybrid-sleep") &&
+ !streq(arg_verb, "suspend-then-hibernate")) {
log_error("Unknown command '%s'.", arg_verb);
return -EINVAL;
}
@@ -199,6 +328,7 @@ static int parse_argv(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
_cleanup_strv_free_ char **modes = NULL, **states = NULL;
+ usec_t delay = 0;
int r;
log_set_target(LOG_TARGET_AUTO);
@@ -209,12 +339,14 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto finish;
- r = parse_sleep_config(arg_verb, &modes, &states);
+ r = parse_sleep_config(arg_verb, &modes, &states, &delay);
if (r < 0)
goto finish;
- r = execute(modes, states);
-
+ if (streq(arg_verb, "suspend-then-hibernate"))
+ r = execute_s2h(delay);
+ else
+ r = execute(modes, states);
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index d4f401d996..3d07483eb4 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 David Strauss
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 David Strauss
***/
#include <errno.h>
diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
index 4c099990ed..519a92a094 100644
--- a/src/stdio-bridge/stdio-bridge.c
+++ b/src/stdio-bridge/stdio-bridge.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
diff --git a/src/sulogin-shell/sulogin-shell.c b/src/sulogin-shell/sulogin-shell.c
index 33dc07c5bd..d0e5a89f1f 100644
--- a/src/sulogin-shell/sulogin-shell.c
+++ b/src/sulogin-shell/sulogin-shell.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2017 Felipe Sateler
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2017 Felipe Sateler
***/
#include <errno.h>
diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
index d97656d6fe..0151f7dabe 100644
--- a/src/sysctl/sysctl.c
+++ b/src/sysctl/sysctl.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <getopt.h>
@@ -32,15 +14,17 @@
#include "fileio.h"
#include "hashmap.h"
#include "log.h"
+#include "pager.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
#include "sysctl-util.h"
+#include "terminal-util.h"
#include "util.h"
static char **arg_prefixes = NULL;
-
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d");
+static bool arg_cat_config = false;
+static bool arg_no_pager = false;
static int apply_all(OrderedHashmap *sysctl_options) {
char *property, *value;
@@ -96,7 +80,7 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign
assert(path);
- r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
+ r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f);
if (r < 0) {
if (ignore_enoent && r == -ENOENT)
return 0;
@@ -181,7 +165,9 @@ static void help(void) {
"Applies kernel sysctl settings.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --cat-config Show configuration files\n"
" --prefix=PATH Only apply rules with the specified prefix\n"
+ " --no-pager Do not pipe output into a pager\n"
, program_invocation_short_name);
}
@@ -189,13 +175,17 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
- ARG_PREFIX
+ ARG_CAT_CONFIG,
+ ARG_PREFIX,
+ ARG_NO_PAGER,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "prefix", required_argument, NULL, ARG_PREFIX },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
+ { "prefix", required_argument, NULL, ARG_PREFIX },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
@@ -215,6 +205,10 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_VERSION:
return version();
+ case ARG_CAT_CONFIG:
+ arg_cat_config = true;
+ break;
+
case ARG_PREFIX: {
char *p;
@@ -237,6 +231,10 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
case '?':
return -EINVAL;
@@ -244,6 +242,11 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached("Unhandled option");
}
+ if (arg_cat_config && argc > optind) {
+ log_error("Positional arguments are not allowed with --cat-config");
+ return -EINVAL;
+ }
+
return 1;
}
@@ -281,12 +284,19 @@ int main(int argc, char *argv[]) {
_cleanup_strv_free_ char **files = NULL;
char **f;
- r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
+ r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("sysctl.d"));
if (r < 0) {
log_error_errno(r, "Failed to enumerate sysctl.d files: %m");
goto finish;
}
+ if (arg_cat_config) {
+ (void) pager_open(arg_no_pager, false);
+
+ r = cat_files(NULL, files, 0);
+ goto finish;
+ }
+
STRV_FOREACH(f, files) {
k = parse_file(sysctl_options, *f, true);
if (k < 0 && r == 0)
@@ -299,6 +309,8 @@ int main(int argc, char *argv[]) {
r = k;
finish:
+ pager_close();
+
ordered_hashmap_free_free_free(sysctl_options);
strv_free(arg_prefixes);
diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c
index ec05e7b9e6..0f77042f48 100644
--- a/src/system-update-generator/system-update-generator.c
+++ b/src/system-update-generator/system-update-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <unistd.h>
@@ -61,9 +43,9 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
*/
if (streq(key, "systemd.unit") && !proc_cmdline_value_missing(key, value))
- log_warning("Offline system update overriden by kernel command line systemd.unit= setting");
+ log_warning("Offline system update overridden by kernel command line systemd.unit= setting");
else if (!value && runlevel_to_target(key))
- log_warning("Offline system update overriden by runlevel \"%s\" on the kernel command line", key);
+ log_warning("Offline system update overridden by runlevel \"%s\" on the kernel command line", key);
return 0;
}
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 3666be61ec..f072ad0c31 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Marc-Antoine Perennou
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Marc-Antoine Perennou
***/
#include <errno.h>
@@ -82,6 +66,7 @@
#include "spawn-polkit-agent.h"
#include "special.h"
#include "stat-util.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit-def.h"
@@ -160,6 +145,7 @@ static enum action {
ACTION_SUSPEND,
ACTION_HIBERNATE,
ACTION_HYBRID_SLEEP,
+ ACTION_SUSPEND_THEN_HIBERNATE,
ACTION_RUNLEVEL2,
ACTION_RUNLEVEL3,
ACTION_RUNLEVEL4,
@@ -222,12 +208,6 @@ static int acquire_bus(BusFocus focus, sd_bus **ret) {
user = arg_scope != UNIT_FILE_SYSTEM;
- if (!user && sd_booted() <= 0) {
- /* Print a friendly message when the local system is actually not running systemd as PID 1. */
- log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
- return -EHOSTDOWN;
- }
-
if (focus == BUS_MANAGER)
r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]);
else
@@ -249,23 +229,7 @@ static void release_busses(void) {
busses[w] = sd_bus_flush_close_unref(busses[w]);
}
-static int map_string_no_copy(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
- char *s;
- const char **p = userdata;
- int r;
-
- r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &s);
- if (r < 0)
- return r;
-
- if (!isempty(s))
- *p = s;
-
- return 0;
-}
-
static void ask_password_agent_open_if_enabled(void) {
-
/* Open the password agent as a child process if necessary */
if (arg_dry_run)
@@ -329,7 +293,6 @@ static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error)
}
static bool install_client_side(void) {
-
/* Decides when to execute enable/disable/... operations
* client-side rather than server-side. */
@@ -450,7 +413,7 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
if (!arg_no_legend &&
(streq(u->active_state, "failed") ||
- STR_IN_SET(u->load_state, "error", "not-found", "masked")))
+ STR_IN_SET(u->load_state, "error", "not-found", "bad-setting", "masked")))
circle_len = 2;
}
@@ -527,7 +490,7 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
underline = true;
}
- if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) {
+ if (STR_IN_SET(u->load_state, "error", "not-found", "bad-setting", "masked") && !arg_plain) {
on_circle = ansi_highlight_yellow();
off_circle = ansi_normal();
circle = true;
@@ -693,8 +656,7 @@ static int get_unit_list(
if (r < 0)
return bus_log_parse_error(r);
- *_reply = reply;
- reply = NULL;
+ *_reply = TAKE_PTR(reply);
return c;
}
@@ -765,16 +727,13 @@ static int get_unit_list_recursive(
}
}
- *_machines = machines;
- machines = NULL;
+ *_machines = TAKE_PTR(machines);
} else
*_machines = NULL;
- *_unit_infos = unit_infos;
- unit_infos = NULL;
+ *_unit_infos = TAKE_PTR(unit_infos);
- *_replies = replies;
- replies = NULL;
+ *_replies = TAKE_PTR(replies);
return c;
}
@@ -790,7 +749,7 @@ static int list_units(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (r < 0)
@@ -1002,7 +961,7 @@ static int list_sockets(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (n < 0)
@@ -1309,7 +1268,7 @@ static int list_timers(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
if (n < 0)
@@ -1347,10 +1306,8 @@ static int list_timers(int argc, char *argv[], void *userdata) {
.id = u->id,
.next_elapse = m,
.last_trigger = last,
- .triggered = triggered,
+ .triggered = TAKE_PTR(triggered),
};
-
- triggered = NULL; /* avoid cleanup */
}
qsort_safe(timer_infos, c, sizeof(struct timer_info),
@@ -1598,7 +1555,7 @@ static int list_unit_files(int argc, char *argv[], void *userdata) {
return bus_log_parse_error(r);
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
output_unit_file_list(units, c);
@@ -1650,93 +1607,74 @@ static int list_dependencies_print(const char *name, int level, unsigned int bra
}
static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
-
- static const char *dependencies[_DEPENDENCY_MAX] = {
- [DEPENDENCY_FORWARD] = "Requires\0"
- "Requisite\0"
- "Wants\0"
- "ConsistsOf\0"
- "BindsTo\0",
- [DEPENDENCY_REVERSE] = "RequiredBy\0"
- "RequisiteOf\0"
- "WantedBy\0"
- "PartOf\0"
- "BoundBy\0",
- [DEPENDENCY_AFTER] = "After\0",
- [DEPENDENCY_BEFORE] = "Before\0",
+ struct DependencyStatusInfo {
+ char **dep[5];
+ } info = {};
+
+ static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = {
+ [DEPENDENCY_FORWARD] = {
+ { "Requires", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
+ { "Requisite", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) },
+ { "Wants", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) },
+ { "ConsistsOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) },
+ { "BindsTo", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) },
+ {}
+ },
+ [DEPENDENCY_REVERSE] = {
+ { "RequiredBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
+ { "RequisiteOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) },
+ { "WantedBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) },
+ { "PartOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) },
+ { "BoundBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) },
+ {}
+ },
+ [DEPENDENCY_AFTER] = {
+ { "After", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
+ {}
+ },
+ [DEPENDENCY_BEFORE] = {
+ { "Before", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) },
+ {}
+ },
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_strv_free_ char **ret = NULL;
_cleanup_free_ char *path = NULL;
- int r;
+ int i, r;
assert(bus);
assert(name);
assert(deps);
- assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
path = unit_dbus_path_from_name(name);
if (!path)
return log_oom();
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &error,
- &reply,
- "s", "org.freedesktop.systemd1.Unit");
+ r = bus_map_all_properties(bus,
+ "org.freedesktop.systemd1",
+ path,
+ map[arg_dependency],
+ BUS_MAP_STRDUP,
+ &error,
+ NULL,
+ &info);
if (r < 0)
return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r));
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *prop;
-
- r = sd_bus_message_read(reply, "s", &prop);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!nulstr_contains(dependencies[arg_dependency], prop)) {
- r = sd_bus_message_skip(reply, "v");
- if (r < 0)
- return bus_log_parse_error(r);
- } else {
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = bus_message_read_strv_extend(reply, &ret);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
+ if (IN_SET(arg_dependency, DEPENDENCY_AFTER, DEPENDENCY_BEFORE)) {
+ *deps = info.dep[0];
+ return 0;
+ }
- r = sd_bus_message_exit_container(reply);
+ for (i = 0; i < 5; i++) {
+ r = strv_extend_strv(&ret, info.dep[i], true);
if (r < 0)
- return bus_log_parse_error(r);
-
+ return log_oom();
+ info.dep[i] = strv_free(info.dep[i]);
}
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- *deps = strv_uniq(ret);
- ret = NULL;
+ *deps = TAKE_PTR(ret);
return 0;
}
@@ -1841,7 +1779,7 @@ static int list_dependencies(int argc, char *argv[], void *userdata) {
int r;
if (argv[1]) {
- r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &unit);
+ r = unit_name_mangle(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &unit);
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
@@ -1853,7 +1791,7 @@ static int list_dependencies(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
puts(u);
@@ -1923,7 +1861,15 @@ static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
bus = container;
}
- r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, NULL, mi);
+ r = bus_map_all_properties(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ machine_info_property_map,
+ BUS_MAP_STRDUP,
+ NULL,
+ NULL,
+ mi);
if (r < 0)
return r;
@@ -1955,8 +1901,7 @@ static int get_machine_list(
return log_oom();
machine_infos[c].is_host = true;
- machine_infos[c].name = hn;
- hn = NULL;
+ machine_infos[c].name = TAKE_PTR(hn);
(void) get_machine_properties(bus, &machine_infos[c]);
c++;
@@ -2085,7 +2030,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
output_machines_list(machine_infos, r);
@@ -2141,13 +2086,13 @@ static int get_default(int argc, char *argv[], void *userdata) {
static int set_default(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *unit = NULL;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
int r;
assert(argc >= 2);
assert(argv);
- r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &unit);
+ r = unit_name_mangle_with_suffix(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, ".target", &unit);
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
@@ -2200,7 +2145,7 @@ finish:
static int output_waiting_jobs(sd_bus *bus, uint32_t id, const char *method, const char *prefix) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *name, *type, *state, *job_path, *unit_path;
+ const char *name, *type;
uint32_t other_id;
int r;
@@ -2222,7 +2167,7 @@ static int output_waiting_jobs(sd_bus *bus, uint32_t id, const char *method, con
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, &state, &job_path, &unit_path)) > 0)
+ while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, NULL, NULL, NULL)) > 0)
printf("%s %u (%s/%s)\n", prefix, other_id, name, type);
if (r < 0)
return bus_log_parse_error(r);
@@ -2257,7 +2202,7 @@ static void output_jobs_list(sd_bus *bus, const struct job_info* jobs, unsigned
return;
}
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
id_len = STRLEN("JOB");
unit_len = STRLEN("UNIT");
@@ -2323,14 +2268,14 @@ static bool output_show_job(struct job_info *job, char **patterns) {
static int list_jobs(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *name, *type, *state, *job_path, *unit_path;
_cleanup_free_ struct job_info *jobs = NULL;
+ const char *name, *type, *state;
+ bool skipped = false;
size_t size = 0;
unsigned c = 0;
sd_bus *bus;
uint32_t id;
int r;
- bool skipped = false;
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -2352,7 +2297,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
+ while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, NULL, NULL)) > 0) {
struct job_info job = { id, name, type, state };
if (!output_show_job(&job, strv_skip(argv, 1))) {
@@ -2372,7 +2317,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
output_jobs_list(bus, jobs, c, skipped);
return 0;
@@ -2493,10 +2438,9 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un
if (r < 0)
return log_error_errno(r, "Failed to access path '%s': %m", path);
- if (unit_path) {
- *unit_path = lpath;
- lpath = NULL;
- }
+ if (unit_path)
+ *unit_path = TAKE_PTR(lpath);
+
return 1;
}
@@ -2528,10 +2472,9 @@ static int unit_find_template_path(
if (r < 0)
return r;
- if (template) {
- *template = _template;
- _template = NULL;
- }
+ if (template)
+ *template = TAKE_PTR(_template);
+
return r;
}
@@ -2631,14 +2574,12 @@ static int unit_find_paths(
r = 0;
if (!isempty(path)) {
- *fragment_path = path;
- path = NULL;
+ *fragment_path = TAKE_PTR(path);
r = 1;
}
if (dropin_paths && !strv_isempty(dropins)) {
- *dropin_paths = dropins;
- dropins = NULL;
+ *dropin_paths = TAKE_PTR(dropins);
r = 1;
}
not_found:
@@ -2682,40 +2623,38 @@ static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *ac
return 0;
}
-static int check_triggering_units(
- sd_bus *bus,
- const char *name) {
+static int unit_is_masked(sd_bus *bus, const char *name) {
+ _cleanup_free_ char *load_state = NULL;
+ int r;
+
+ r = unit_load_state(bus, name, &load_state);
+ if (r < 0)
+ return r;
+
+ return streq(load_state, "masked");
+}
+static int check_triggering_units(sd_bus *bus, const char *name) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *path = NULL, *n = NULL, *load_state = NULL;
+ _cleanup_free_ char *n = NULL, *path = NULL;
_cleanup_strv_free_ char **triggered_by = NULL;
bool print_warning_label = true;
UnitActiveState active_state;
char **i;
int r;
- r = unit_name_mangle(name, UNIT_NAME_NOGLOB, &n);
+ r = unit_name_mangle(name, 0, &n);
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
+ r = unit_is_masked(bus, n);
+ if (r != 0)
+ return r < 0 ? r : 0;
+
path = unit_dbus_path_from_name(n);
if (!path)
return log_oom();
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Unit",
- "LoadState",
- &error,
- &load_state);
- if (r < 0)
- return log_error_errno(r, "Failed to get load state of %s: %s", n, bus_error_message(&error, r));
-
- if (streq(load_state, "masked"))
- return 0;
-
r = sd_bus_get_property_strv(
bus,
"org.freedesktop.systemd1",
@@ -2980,11 +2919,12 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r
STRV_FOREACH(name, names) {
char *t;
+ UnitNameMangle options = UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN);
if (suffix)
- r = unit_name_mangle_with_suffix(*name, UNIT_NAME_GLOB, suffix, &t);
+ r = unit_name_mangle_with_suffix(*name, options, suffix, &t);
else
- r = unit_name_mangle(*name, UNIT_NAME_GLOB, &t);
+ r = unit_name_mangle(*name, options, &t);
if (r < 0)
return log_error_errno(r, "Failed to mangle name: %m");
@@ -3022,8 +2962,7 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r
}
}
- *ret = mangled;
- mangled = NULL; /* do not free */
+ *ret = TAKE_PTR(mangled);
return 0;
}
@@ -3033,21 +2972,22 @@ static const struct {
const char *verb;
const char *mode;
} action_table[_ACTION_MAX] = {
- [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
- [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
- [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
- [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
- [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
- [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
- [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
- [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
- [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
- [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
- [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
- [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
- [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
- [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
- [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
+ [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
+ [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
+ [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
+ [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
+ [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
+ [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
+ [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
+ [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
+ [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
+ [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
+ [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
+ [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
+ [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
+ [ACTION_SUSPEND_THEN_HIBERNATE] = { SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, "suspend-then-hibernate", "replace-irreversibly" },
};
static enum action verb_to_action(const char *verb) {
@@ -3282,6 +3222,11 @@ static int logind_reboot(enum action a) {
description = "put system into hybrid sleep";
break;
+ case ACTION_SUSPEND_THEN_HIBERNATE:
+ method = "SuspendThenHibernate";
+ description = "put system into suspend followed by hibernate";
+ break;
+
default:
return -EINVAL;
}
@@ -3650,7 +3595,8 @@ static int start_special(int argc, char *argv[], void *userdata) {
ACTION_HALT,
ACTION_SUSPEND,
ACTION_HIBERNATE,
- ACTION_HYBRID_SLEEP)) {
+ ACTION_HYBRID_SLEEP,
+ ACTION_SUSPEND_THEN_HIBERNATE)) {
r = logind_reboot(a);
if (r >= 0)
@@ -3941,6 +3887,7 @@ typedef struct UnitStatusInfo {
/* Socket */
unsigned n_accepted;
unsigned n_connections;
+ unsigned n_refused;
bool accept;
/* Pairs of type, path */
@@ -3996,11 +3943,11 @@ static void print_status_info(
UnitStatusInfo *i,
bool *ellipsized) {
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2, *active_on, *active_off, *on, *off, *ss;
+ _cleanup_free_ char *formatted_path = NULL;
ExecStatusInfo *p;
- const char *active_on, *active_off, *on, *off, *ss;
usec_t timestamp;
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
const char *path;
char **t, **t2;
int r;
@@ -4029,15 +3976,17 @@ static void print_status_info(
if (i->following)
printf(" Follow: unit currently follows state of %s\n", i->following);
- if (streq_ptr(i->load_state, "error")) {
+ if (STRPTR_IN_SET(i->load_state, "error", "not-found", "bad-setting")) {
on = ansi_highlight_red();
off = ansi_normal();
} else
on = off = "";
- path = i->source_path ? i->source_path : i->fragment_path;
+ path = i->source_path ?: i->fragment_path;
+ if (path && terminal_urlify_path(path, NULL, &formatted_path) >= 0)
+ path = formatted_path;
- if (i->load_error != 0)
+ if (!isempty(i->load_error))
printf(" Loaded: %s%s%s (Reason: %s)\n",
on, strna(i->load_state), off, i->load_error);
else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset) &&
@@ -4063,6 +4012,9 @@ static void print_status_info(
char ** dropin;
STRV_FOREACH(dropin, i->dropin_paths) {
+ _cleanup_free_ char *dropin_formatted = NULL;
+ const char *df;
+
if (!dir || last) {
printf(dir ? " " :
" Drop-In: ");
@@ -4082,7 +4034,12 @@ static void print_status_info(
last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
- printf("%s%s", basename(*dropin), last ? "\n" : ", ");
+ if (terminal_urlify_path(*dropin, basename(*dropin), &dropin_formatted) >= 0)
+ df = dropin_formatted;
+ else
+ df = *dropin;
+
+ printf("%s%s", df, last ? "\n" : ", ");
}
}
@@ -4115,7 +4072,7 @@ static void print_status_info(
if (endswith(i->id, ".timer")) {
char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX],
tstamp2[FORMAT_TIMESTAMP_MAX];
- char *next_rel_time, *next_time;
+ const char *next_rel_time, *next_time;
dual_timestamp nw, next = {i->next_elapse_real,
i->next_elapse_monotonic};
usec_t next_elapse;
@@ -4124,12 +4081,8 @@ static void print_status_info(
dual_timestamp_get(&nw);
next_elapse = calc_next_elapse(&nw, &next);
- next_rel_time = format_timestamp_relative(tstamp1,
- sizeof(tstamp1),
- next_elapse);
- next_time = format_timestamp(tstamp2,
- sizeof(tstamp2),
- next_elapse);
+ next_rel_time = format_timestamp_relative(tstamp1, sizeof tstamp1, next_elapse);
+ next_time = format_timestamp(tstamp2, sizeof tstamp2, next_elapse);
if (next_time && next_rel_time)
printf("%s; %s\n", next_time, next_rel_time);
@@ -4185,14 +4138,27 @@ static void print_status_info(
if (i->what)
printf(" What: %s\n", i->what);
- STRV_FOREACH(t, i->documentation)
- printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
+ STRV_FOREACH(t, i->documentation) {
+ _cleanup_free_ char *formatted = NULL;
+ const char *q;
+
+ if (terminal_urlify(*t, NULL, &formatted) >= 0)
+ q = formatted;
+ else
+ q = *t;
+
+ printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", q);
+ }
STRV_FOREACH_PAIR(t, t2, i->listen)
printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
- if (i->accept)
- printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
+ if (i->accept) {
+ printf(" Accepted: %u; Connected: %u;", i->n_accepted, i->n_connections);
+ if (i->n_refused)
+ printf(" Refused: %u", i->n_refused);
+ printf("\n");
+ }
LIST_FOREACH(exec, p, i->exec) {
_cleanup_free_ char *argv = NULL;
@@ -4381,7 +4347,7 @@ static void print_status_info(
show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
} else if (r < 0)
- log_warning_errno(r, "Failed to dump process list, ignoring: %s", bus_error_message(&error, r));
+ log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s", i->id, bus_error_message(&error, r));
}
if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
@@ -4419,354 +4385,164 @@ static void show_unit_help(UnitStatusInfo *i) {
log_info("Can't show: %s", *p);
}
-static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
+static int map_main_pid(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ uint32_t u;
int r;
- assert(name);
- assert(m);
- assert(i);
-
- switch (contents[0]) {
-
- case SD_BUS_TYPE_STRING: {
- const char *s;
-
- r = sd_bus_message_read(m, "s", &s);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!isempty(s)) {
- if (streq(name, "Id"))
- i->id = s;
- else if (streq(name, "LoadState"))
- i->load_state = s;
- else if (streq(name, "ActiveState"))
- i->active_state = s;
- else if (streq(name, "SubState"))
- i->sub_state = s;
- else if (streq(name, "Description"))
- i->description = s;
- else if (streq(name, "FragmentPath"))
- i->fragment_path = s;
- else if (streq(name, "SourcePath"))
- i->source_path = s;
-#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"))
- i->where = s;
- else if (streq(name, "What"))
- i->what = s;
- else if (streq(name, "Following"))
- i->following = s;
- else if (streq(name, "UnitFileState"))
- i->unit_file_state = s;
- else if (streq(name, "UnitFilePreset"))
- i->unit_file_preset = s;
- else if (streq(name, "Result"))
- i->result = s;
- }
-
- break;
- }
+ r = sd_bus_message_read(m, "u", &u);
+ if (r < 0)
+ return r;
- case SD_BUS_TYPE_BOOLEAN: {
- int b;
+ i->main_pid = (pid_t) u;
+ i->running = u > 0;
- r = sd_bus_message_read(m, "b", &b);
- if (r < 0)
- return bus_log_parse_error(r);
+ return 0;
+}
- if (streq(name, "Accept"))
- i->accept = b;
- else if (streq(name, "NeedDaemonReload"))
- i->need_daemon_reload = b;
- else if (streq(name, "ConditionResult"))
- i->condition_result = b;
- else if (streq(name, "AssertResult"))
- i->assert_result = b;
- else if (streq(name, "Transient"))
- i->transient = b;
+static int map_load_error(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ const char *message, **p = userdata;
+ int r;
- break;
- }
+ r = sd_bus_message_read(m, "(ss)", NULL, &message);
+ if (r < 0)
+ return r;
- case SD_BUS_TYPE_UINT32: {
- uint32_t u;
+ if (!isempty(message))
+ *p = message;
- r = sd_bus_message_read(m, "u", &u);
- if (r < 0)
- return bus_log_parse_error(r);
+ return 0;
+}
- if (streq(name, "MainPID")) {
- if (u > 0) {
- i->main_pid = (pid_t) u;
- i->running = true;
- }
- } else if (streq(name, "ControlPID"))
- i->control_pid = (pid_t) u;
- else if (streq(name, "ExecMainPID")) {
- if (u > 0)
- i->main_pid = (pid_t) u;
- } else if (streq(name, "NAccepted"))
- i->n_accepted = u;
- else if (streq(name, "NConnections"))
- i->n_connections = u;
+static int map_listen(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ const char *type, *path;
+ char ***p = userdata;
+ int r;
- break;
- }
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return r;
- case SD_BUS_TYPE_INT32: {
- int32_t j;
+ while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
- r = sd_bus_message_read(m, "i", &j);
+ r = strv_extend(p, type);
if (r < 0)
- return bus_log_parse_error(r);
-
- if (streq(name, "ExecMainCode"))
- i->exit_code = (int) j;
- else if (streq(name, "ExecMainStatus"))
- i->exit_status = (int) j;
- else if (streq(name, "StatusErrno"))
- i->status_errno = (int) j;
-
- break;
- }
-
- case SD_BUS_TYPE_UINT64: {
- uint64_t u;
+ return r;
- r = sd_bus_message_read(m, "t", &u);
+ r = strv_extend(p, path);
if (r < 0)
- return bus_log_parse_error(r);
-
- if (streq(name, "ExecMainStartTimestamp"))
- i->start_timestamp = (usec_t) u;
- else if (streq(name, "ExecMainExitTimestamp"))
- i->exit_timestamp = (usec_t) u;
- else if (streq(name, "ActiveEnterTimestamp"))
- i->active_enter_timestamp = (usec_t) u;
- else if (streq(name, "InactiveEnterTimestamp"))
- i->inactive_enter_timestamp = (usec_t) u;
- else if (streq(name, "InactiveExitTimestamp"))
- i->inactive_exit_timestamp = (usec_t) u;
- else if (streq(name, "InactiveExitTimestampMonotonic"))
- i->inactive_exit_timestamp_monotonic = (usec_t) u;
- else if (streq(name, "ActiveExitTimestamp"))
- i->active_exit_timestamp = (usec_t) u;
- else if (streq(name, "ConditionTimestamp"))
- i->condition_timestamp = (usec_t) u;
- else if (streq(name, "AssertTimestamp"))
- i->assert_timestamp = (usec_t) u;
- else if (streq(name, "MemoryCurrent"))
- i->memory_current = u;
- else if (streq(name, "MemoryLow"))
- i->memory_low = u;
- else if (streq(name, "MemoryHigh"))
- i->memory_high = u;
- else if (streq(name, "MemoryMax"))
- i->memory_max = u;
- else if (streq(name, "MemorySwapMax"))
- i->memory_swap_max = u;
- else if (streq(name, "MemoryLimit"))
- i->memory_limit = u;
- else if (streq(name, "TasksCurrent"))
- i->tasks_current = u;
- else if (streq(name, "TasksMax"))
- i->tasks_max = u;
- else if (streq(name, "CPUUsageNSec"))
- i->cpu_usage_nsec = u;
- else if (streq(name, "NextElapseUSecMonotonic"))
- i->next_elapse_monotonic = u;
- else if (streq(name, "NextElapseUSecRealtime"))
- i->next_elapse_real = u;
- else if (streq(name, "IPIngressBytes"))
- i->ip_ingress_bytes = u;
- else if (streq(name, "IPEgressBytes"))
- i->ip_egress_bytes = u;
-
- break;
+ return r;
}
+ if (r < 0)
+ return r;
- case SD_BUS_TYPE_ARRAY:
-
- if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
- _cleanup_free_ ExecStatusInfo *info = NULL;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- info = new0(ExecStatusInfo, 1);
- if (!info)
- return log_oom();
-
- while ((r = exec_status_info_deserialize(m, info)) > 0) {
-
- info->name = strdup(name);
- if (!info->name)
- return log_oom();
-
- LIST_PREPEND(exec, i->exec, info);
-
- info = new0(ExecStatusInfo, 1);
- if (!info)
- return log_oom();
- }
-
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 0;
-
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
- const char *type, *path;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
-
- r = strv_extend(&i->listen, type);
- if (r < 0)
- return r;
-
- r = strv_extend(&i->listen, path);
- if (r < 0)
- return r;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 0;
-
- } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
-
- r = sd_bus_message_read_strv(m, &i->dropin_paths);
- if (r < 0)
- return bus_log_parse_error(r);
-
- } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
- r = sd_bus_message_read_strv(m, &i->documentation);
- if (r < 0)
- return bus_log_parse_error(r);
+ return 0;
+}
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
- const char *cond, *param;
- int trigger, negate;
- int32_t state;
+static int map_conditions(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ const char *cond, *param;
+ int trigger, negate;
+ int32_t state;
+ int r;
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
- if (r < 0)
- return bus_log_parse_error(r);
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
+ if (r < 0)
+ return r;
- while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
- _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
+ while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
+ _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
- log_debug("%s trigger=%d negate=%d %s →%d", cond, trigger, negate, param, state);
+ c = new0(UnitCondition, 1);
+ if (!c)
+ return -ENOMEM;
- c = new0(UnitCondition, 1);
- if (!c)
- return log_oom();
+ c->name = strdup(cond);
+ c->param = strdup(param);
+ if (!c->name || !c->param)
+ return -ENOMEM;
- c->name = strdup(cond);
- c->param = strdup(param);
- if (!c->name || !c->param)
- return log_oom();
+ c->trigger = trigger;
+ c->negate = negate;
+ c->tristate = state;
- c->trigger = trigger;
- c->negate = negate;
- c->tristate = state;
+ LIST_PREPEND(conditions, i->conditions, c);
+ c = NULL;
+ }
+ if (r < 0)
+ return r;
- LIST_PREPEND(conditions, i->conditions, c);
- c = NULL;
- }
- if (r < 0)
- return bus_log_parse_error(r);
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
+ return 0;
+}
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
- const char *cond, *param;
- int trigger, negate;
- int32_t state;
+static int map_asserts(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ UnitStatusInfo *i = userdata;
+ const char *cond, *param;
+ int trigger, negate;
+ int32_t state;
+ int r;
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
- if (r < 0)
- return bus_log_parse_error(r);
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
+ if (r < 0)
+ return r;
- while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
- log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
- if (state < 0 && (!trigger || !i->failed_assert)) {
- i->failed_assert = cond;
- i->failed_assert_trigger = trigger;
- i->failed_assert_negate = negate;
- i->failed_assert_parameter = param;
- }
- }
- if (r < 0)
- return bus_log_parse_error(r);
+ while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
+ if (state < 0 && (!trigger || !i->failed_assert)) {
+ i->failed_assert = cond;
+ i->failed_assert_trigger = trigger;
+ i->failed_assert_negate = negate;
+ i->failed_assert_parameter = param;
+ }
+ }
+ if (r < 0)
+ return r;
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
- } else
- goto skip;
+ return 0;
+}
- break;
+static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ _cleanup_free_ ExecStatusInfo *info = NULL;
+ UnitStatusInfo *i = userdata;
+ int r;
- case SD_BUS_TYPE_STRUCT_BEGIN:
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
+ if (r < 0)
+ return r;
- if (streq(name, "LoadError")) {
- const char *n, *message;
+ info = new0(ExecStatusInfo, 1);
+ if (!info)
+ return -ENOMEM;
- r = sd_bus_message_read(m, "(ss)", &n, &message);
- if (r < 0)
- return bus_log_parse_error(r);
+ while ((r = exec_status_info_deserialize(m, info)) > 0) {
- if (!isempty(message))
- i->load_error = message;
- } else
- goto skip;
+ info->name = strdup(member);
+ if (!info->name)
+ return -ENOMEM;
- break;
+ LIST_PREPEND(exec, i->exec, info);
- default:
- goto skip;
+ info = new0(ExecStatusInfo, 1);
+ if (!info)
+ return -ENOMEM;
}
+ if (r < 0)
+ return r;
- return 0;
-
-skip:
- r = sd_bus_message_skip(m, contents);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
- return bus_log_parse_error(r);
+ return r;
return 0;
}
@@ -4779,7 +4555,9 @@ skip:
printf("%s=" fmt "\n", name, __VA_ARGS__); \
} while (0)
-static int print_property(const char *name, sd_bus_message *m, const char *contents) {
+static int print_property(const char *name, sd_bus_message *m, bool value, bool all) {
+ char bus_type;
+ const char *contents;
int r;
assert(name);
@@ -4788,17 +4566,15 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
/* This is a low-level property printer, see
* print_status_info() for the nicer output */
- if (arg_properties && !strv_find(arg_properties, name)) {
- /* skip what we didn't read */
- r = sd_bus_message_skip(m, contents);
+ r = sd_bus_message_peek_type(m, &bus_type, &contents);
+ if (r < 0)
return r;
- }
- switch (contents[0]) {
+ switch (bus_type) {
- case SD_BUS_TYPE_STRUCT_BEGIN:
+ case SD_BUS_TYPE_STRUCT:
- if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
+ if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
uint32_t u;
r = sd_bus_message_read(m, "(uo)", &u, NULL);
@@ -4807,34 +4583,34 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (u > 0)
print_prop(name, "%"PRIu32, u);
- else if (arg_all)
+ else if (all)
print_prop(name, "%s", "");
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
const char *s;
r = sd_bus_message_read(m, "(so)", &s, NULL);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || !isempty(s))
+ if (all || !isempty(s))
print_prop(name, "%s", s);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
const char *a = NULL, *b = NULL;
r = sd_bus_message_read(m, "(ss)", &a, &b);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || !isempty(a) || !isempty(b))
+ if (all || !isempty(a) || !isempty(b))
print_prop(name, "%s \"%s\"", strempty(a), strempty(b));
- return 0;
+ return 1;
} else if (streq_ptr(name, "SystemCallFilter")) {
_cleanup_strv_free_ char **l = NULL;
int whitelist;
@@ -4855,11 +4631,11 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || whitelist || !strv_isempty(l)) {
+ if (all || whitelist || !strv_isempty(l)) {
bool first = true;
char **i;
- if (!arg_value) {
+ if (!value) {
fputs(name, stdout);
fputc('=', stdout);
}
@@ -4878,14 +4654,14 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
fputc('\n', stdout);
}
- return 0;
+ return 1;
}
break;
case SD_BUS_TYPE_ARRAY:
- if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
+ if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
const char *path;
int ignore;
@@ -4903,9 +4679,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
const char *type, *path;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
@@ -4921,9 +4697,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
const char *type, *path;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
@@ -4939,21 +4715,21 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) {
const char *base;
- uint64_t value, next_elapse;
+ uint64_t v, next_elapse;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
if (r < 0)
return bus_log_parse_error(r);
- while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
+ while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0) {
char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
print_prop(name, "{ %s=%s ; next_elapse=%s }", base,
- format_timespan(timespan1, sizeof(timespan1), value, 0),
+ format_timespan(timespan1, sizeof(timespan1), v, 0),
format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
}
if (r < 0)
@@ -4963,9 +4739,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) {
const char *base, *spec;
uint64_t next_elapse;
@@ -4986,9 +4762,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
ExecStatusInfo info = {};
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
@@ -5023,9 +4799,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
const char *path, *rwm;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
@@ -5041,9 +4817,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
const char *path;
uint64_t weight;
@@ -5061,9 +4837,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
+ } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN &&
(cgroup_io_limit_type_from_string(name) >= 0 ||
STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
const char *path;
@@ -5082,9 +4858,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_BYTE && streq(name, "StandardInputData")) {
+ } else if (contents[0] == SD_BUS_TYPE_BYTE && streq(name, "StandardInputData")) {
_cleanup_free_ char *h = NULL;
const void *p;
size_t sz;
@@ -5100,40 +4876,111 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
print_prop(name, "%s", h);
- return 0;
+ return 1;
}
break;
}
- r = bus_print_property(name, m, arg_value, arg_all);
- if (r < 0)
- return bus_log_parse_error(r);
+ return 0;
+}
- if (r == 0) {
- r = sd_bus_message_skip(m, contents);
- if (r < 0)
- return bus_log_parse_error(r);
+typedef enum SystemctlShowMode{
+ SYSTEMCTL_SHOW_PROPERTIES,
+ SYSTEMCTL_SHOW_STATUS,
+ SYSTEMCTL_SHOW_HELP,
+ _SYSTEMCTL_SHOW_MODE_MAX,
+ _SYSTEMCTL_SHOW_MODE_INVALID = -1,
+} SystemctlShowMode;
- if (arg_all)
- printf("%s=[unprintable]\n", name);
- }
+static const char* const systemctl_show_mode_table[] = {
+ [SYSTEMCTL_SHOW_PROPERTIES] = "show",
+ [SYSTEMCTL_SHOW_STATUS] = "status",
+ [SYSTEMCTL_SHOW_HELP] = "help",
+};
- return 0;
-}
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode, SystemctlShowMode);
static int show_one(
- const char *verb,
sd_bus *bus,
const char *path,
const char *unit,
- bool show_properties,
+ SystemctlShowMode show_mode,
bool *new_line,
bool *ellipsized) {
static const struct bus_properties_map property_map[] = {
- { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
- { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state) },
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
+ { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
+ {}
+ }, status_map[] = {
+ { "Id", "s", NULL, offsetof(UnitStatusInfo, id) },
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
+ { "SubState", "s", NULL, offsetof(UnitStatusInfo, sub_state) },
+ { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) },
+ { "UnitFilePreset", "s", NULL, offsetof(UnitStatusInfo, unit_file_preset) },
+ { "Description", "s", NULL, offsetof(UnitStatusInfo, description) },
+ { "Following", "s", NULL, offsetof(UnitStatusInfo, following) },
+ { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) },
+ { "FragmentPath", "s", NULL, offsetof(UnitStatusInfo, fragment_path) },
+ { "SourcePath", "s", NULL, offsetof(UnitStatusInfo, source_path) },
+ { "ControlGroup", "s", NULL, offsetof(UnitStatusInfo, control_group) },
+ { "DropInPaths", "as", NULL, offsetof(UnitStatusInfo, dropin_paths) },
+ { "LoadError", "(ss)", map_load_error, offsetof(UnitStatusInfo, load_error) },
+ { "Result", "s", NULL, offsetof(UnitStatusInfo, result) },
+ { "InactiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp) },
+ { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp_monotonic) },
+ { "ActiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_enter_timestamp) },
+ { "ActiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_exit_timestamp) },
+ { "InactiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_enter_timestamp) },
+ { "NeedDaemonReload", "b", NULL, offsetof(UnitStatusInfo, need_daemon_reload) },
+ { "Transient", "b", NULL, offsetof(UnitStatusInfo, transient) },
+ { "ExecMainPID", "u", NULL, offsetof(UnitStatusInfo, main_pid) },
+ { "MainPID", "u", map_main_pid, 0 },
+ { "ControlPID", "u", NULL, offsetof(UnitStatusInfo, control_pid) },
+ { "StatusText", "s", NULL, offsetof(UnitStatusInfo, status_text) },
+ { "PIDFile", "s", NULL, offsetof(UnitStatusInfo, pid_file) },
+ { "StatusErrno", "i", NULL, offsetof(UnitStatusInfo, status_errno) },
+ { "ExecMainStartTimestamp", "t", NULL, offsetof(UnitStatusInfo, start_timestamp) },
+ { "ExecMainExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, exit_timestamp) },
+ { "ExecMainCode", "i", NULL, offsetof(UnitStatusInfo, exit_code) },
+ { "ExecMainStatus", "i", NULL, offsetof(UnitStatusInfo, exit_status) },
+ { "ConditionTimestamp", "t", NULL, offsetof(UnitStatusInfo, condition_timestamp) },
+ { "ConditionResult", "b", NULL, offsetof(UnitStatusInfo, condition_result) },
+ { "Conditions", "a(sbbsi)", map_conditions, 0 },
+ { "AssertTimestamp", "t", NULL, offsetof(UnitStatusInfo, assert_timestamp) },
+ { "AssertResult", "b", NULL, offsetof(UnitStatusInfo, assert_result) },
+ { "Asserts", "a(sbbsi)", map_asserts, 0 },
+ { "NextElapseUSecRealtime", "t", NULL, offsetof(UnitStatusInfo, next_elapse_real) },
+ { "NextElapseUSecMonotonic", "t", NULL, offsetof(UnitStatusInfo, next_elapse_monotonic) },
+ { "NAccepted", "u", NULL, offsetof(UnitStatusInfo, n_accepted) },
+ { "NConnections", "u", NULL, offsetof(UnitStatusInfo, n_connections) },
+ { "NRefused", "u", NULL, offsetof(UnitStatusInfo, n_refused) },
+ { "Accept", "b", NULL, offsetof(UnitStatusInfo, accept) },
+ { "Listen", "a(ss)", map_listen, offsetof(UnitStatusInfo, listen) },
+ { "SysFSPath", "s", NULL, offsetof(UnitStatusInfo, sysfs_path) },
+ { "Where", "s", NULL, offsetof(UnitStatusInfo, where) },
+ { "What", "s", NULL, offsetof(UnitStatusInfo, what) },
+ { "MemoryCurrent", "t", NULL, offsetof(UnitStatusInfo, memory_current) },
+ { "MemoryLow", "t", NULL, offsetof(UnitStatusInfo, memory_low) },
+ { "MemoryHigh", "t", NULL, offsetof(UnitStatusInfo, memory_high) },
+ { "MemoryMax", "t", NULL, offsetof(UnitStatusInfo, memory_max) },
+ { "MemorySwapMax", "t", NULL, offsetof(UnitStatusInfo, memory_swap_max) },
+ { "MemoryLimit", "t", NULL, offsetof(UnitStatusInfo, memory_limit) },
+ { "CPUUsageNSec", "t", NULL, offsetof(UnitStatusInfo, cpu_usage_nsec) },
+ { "TasksCurrent", "t", NULL, offsetof(UnitStatusInfo, tasks_current) },
+ { "TasksMax", "t", NULL, offsetof(UnitStatusInfo, tasks_max) },
+ { "IPIngressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_ingress_bytes) },
+ { "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) },
+ { "ExecStartPre", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStart", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStartPost", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecReload", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStopPre", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStop", "a(sasbttttuii)", map_exec, 0 },
+ { "ExecStopPost", "a(sasbttttuii)", map_exec, 0 },
{}
};
@@ -5152,6 +4999,7 @@ static int show_one(
.ip_ingress_bytes = (uint64_t) -1,
.ip_egress_bytes = (uint64_t) -1,
};
+ char **pp;
int r;
assert(path);
@@ -5159,113 +5007,59 @@ static int show_one(
log_debug("Showing one %s", path);
- r = sd_bus_call_method(
+ r = bus_map_all_properties(
bus,
"org.freedesktop.systemd1",
path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
+ show_mode == SYSTEMCTL_SHOW_STATUS ? status_map : property_map,
+ BUS_MAP_BOOLEAN_AS_BOOL,
&error,
&reply,
- "s", "");
+ &info);
if (r < 0)
return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
- if (unit) {
- r = bus_message_map_all_properties(reply, property_map, &error, &info);
- if (r < 0)
- return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
-
- if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
- log_full(streq(verb, "status") ? LOG_ERR : LOG_DEBUG,
- "Unit %s could not be found.", unit);
+ if (unit && streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
+ log_full(show_mode == SYSTEMCTL_SHOW_STATUS ? LOG_ERR : LOG_DEBUG,
+ "Unit %s could not be found.", unit);
- if (streq(verb, "status"))
- return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
-
- if (!streq(verb, "show"))
- return -ENOENT;
- }
-
- r = sd_bus_message_rewind(reply, true);
- if (r < 0)
- return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
+ if (show_mode == SYSTEMCTL_SHOW_STATUS)
+ return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
+ else if (show_mode == SYSTEMCTL_SHOW_HELP)
+ return -ENOENT;
}
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
if (*new_line)
printf("\n");
*new_line = true;
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *name, *contents;
-
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_peek_type(reply, NULL, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (show_properties) {
- r = set_ensure_allocated(&found_properties, &string_hash_ops);
- if (r < 0)
- return log_oom();
-
- r = set_put(found_properties, name);
- if (r < 0 && r != EEXIST)
- return log_oom();
+ if (show_mode == SYSTEMCTL_SHOW_STATUS) {
+ print_status_info(bus, &info, ellipsized);
- r = print_property(name, reply, contents);
- } else
- r = status_property(name, reply, &info, contents);
- if (r < 0)
- return r;
+ if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
+ return EXIT_PROGRAM_NOT_RUNNING;
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
+ return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
+ } else if (show_mode == SYSTEMCTL_SHOW_HELP) {
+ show_unit_help(&info);
+ return 0;
}
+
+ r = sd_bus_message_rewind(reply, true);
if (r < 0)
- return bus_log_parse_error(r);
+ return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
- r = sd_bus_message_exit_container(reply);
+ r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_value, arg_all, &found_properties);
if (r < 0)
return bus_log_parse_error(r);
- r = 0;
- if (show_properties) {
- char **pp;
-
- STRV_FOREACH(pp, arg_properties)
- if (!set_contains(found_properties, *pp))
- log_debug("Property %s does not exist.", *pp);
-
- } else if (streq(verb, "help"))
- show_unit_help(&info);
- else if (streq(verb, "status")) {
- print_status_info(bus, &info, ellipsized);
-
- if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
- r = EXIT_PROGRAM_NOT_RUNNING;
- else
- r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
- }
+ STRV_FOREACH(pp, arg_properties)
+ if (!set_contains(found_properties, *pp))
+ log_debug("Property %s does not exist.", *pp);
- return r;
+ return 0;
}
static int get_unit_dbus_path_by_pid(
@@ -5303,9 +5097,7 @@ static int get_unit_dbus_path_by_pid(
}
static int show_all(
- const char* verb,
sd_bus *bus,
- bool show_properties,
bool *new_line,
bool *ellipsized) {
@@ -5319,7 +5111,7 @@ static int show_all(
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
c = (unsigned) r;
@@ -5332,7 +5124,7 @@ static int show_all(
if (!p)
return log_oom();
- r = show_one(verb, bus, p, u->id, show_properties, new_line, ellipsized);
+ r = show_one(bus, p, u->id, SYSTEMCTL_SHOW_STATUS, new_line, ellipsized);
if (r < 0)
return r;
else if (r > 0 && ret == 0)
@@ -5354,7 +5146,15 @@ static int show_system_status(sd_bus *bus) {
if (!hn)
return log_oom();
- r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &error, &mi);
+ r = bus_map_all_properties(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ machine_info_property_map,
+ BUS_MAP_STRDUP,
+ &error,
+ NULL,
+ &mi);
if (r < 0)
return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r));
@@ -5401,18 +5201,20 @@ static int show_system_status(sd_bus *bus) {
}
static int show(int argc, char *argv[], void *userdata) {
- bool show_properties, show_status, show_help, new_line = false;
- bool ellipsized = false;
+ bool new_line = false, ellipsized = false;
+ SystemctlShowMode show_mode;
int r, ret = 0;
sd_bus *bus;
assert(argv);
- show_properties = streq(argv[0], "show");
- show_status = streq(argv[0], "status");
- show_help = streq(argv[0], "help");
+ show_mode = systemctl_show_mode_from_string(argv[0]);
+ if (show_mode < 0) {
+ log_error("Invalid argument.");
+ return -EINVAL;
+ }
- if (show_help && argc <= 1) {
+ if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1) {
log_error("This command expects one or more unit names. Did you mean --help?");
return -EINVAL;
}
@@ -5421,25 +5223,25 @@ static int show(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
- if (show_status)
+ if (show_mode == SYSTEMCTL_SHOW_STATUS)
/* Increase max number of open files to 16K if we can, we
* might needs this when browsing journal files, which might
* be split up into many files. */
setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
/* If no argument is specified inspect the manager itself */
- if (show_properties && argc <= 1)
- return show_one(argv[0], bus, "/org/freedesktop/systemd1", NULL, show_properties, &new_line, &ellipsized);
+ if (show_mode == SYSTEMCTL_SHOW_PROPERTIES && argc <= 1)
+ return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
- if (show_status && argc <= 1) {
+ if (show_mode == SYSTEMCTL_SHOW_STATUS && argc <= 1) {
show_system_status(bus);
new_line = true;
if (arg_all)
- ret = show_all(argv[0], bus, false, &new_line, &ellipsized);
+ ret = show_all(bus, &new_line, &ellipsized);
} else {
_cleanup_free_ char **patterns = NULL;
char **name;
@@ -5453,7 +5255,7 @@ static int show(int argc, char *argv[], void *userdata) {
return log_oom();
continue;
- } else if (show_properties) {
+ } else if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) {
/* Interpret as job id */
if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
return log_oom();
@@ -5471,7 +5273,7 @@ static int show(int argc, char *argv[], void *userdata) {
return log_oom();
}
- r = show_one(argv[0], bus, path, unit, show_properties, &new_line, &ellipsized);
+ r = show_one(bus, path, unit, show_mode, &new_line, &ellipsized);
if (r < 0)
return r;
else if (r > 0 && ret == 0)
@@ -5492,7 +5294,7 @@ static int show(int argc, char *argv[], void *userdata) {
if (!path)
return log_oom();
- r = show_one(argv[0], bus, path, *name, show_properties, &new_line, &ellipsized);
+ r = show_one(bus, path, *name, show_mode, &new_line, &ellipsized);
if (r < 0)
return r;
if (r > 0 && ret == 0)
@@ -5507,25 +5309,8 @@ static int show(int argc, char *argv[], void *userdata) {
return ret;
}
-static int cat_file(const char *filename, bool newline) {
- _cleanup_close_ int fd;
-
- fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
-
- printf("%s%s# %s%s\n",
- newline ? "\n" : "",
- ansi_highlight_blue(),
- filename,
- ansi_normal());
- fflush(stdout);
-
- return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0);
-}
-
static int cat(int argc, char *argv[], void *userdata) {
- _cleanup_lookup_paths_free_ LookupPaths lp = {};
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
_cleanup_strv_free_ char **names = NULL;
char **name;
sd_bus *bus;
@@ -5549,12 +5334,11 @@ static int cat(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to expand names: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
STRV_FOREACH(name, names) {
_cleanup_free_ char *fragment_path = NULL;
_cleanup_strv_free_ char **dropin_paths = NULL;
- char **path;
r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths);
if (r < 0)
@@ -5581,17 +5365,9 @@ static int cat(int argc, char *argv[], void *userdata) {
arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
ansi_normal());
- if (fragment_path) {
- r = cat_file(fragment_path, false);
- if (r < 0)
- return log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
- }
-
- STRV_FOREACH(path, dropin_paths) {
- r = cat_file(*path, path == dropin_paths);
- if (r < 0)
- return log_warning_errno(r, "Failed to cat %s: %m", *path);
- }
+ r = cat_files(fragment_path, dropin_paths, 0);
+ if (r < 0)
+ return r;
}
return 0;
@@ -5621,7 +5397,7 @@ static int set_property(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &n);
+ r = unit_name_mangle(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &n);
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
@@ -5828,7 +5604,7 @@ static int show_environment(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_get_property(
bus,
@@ -5883,7 +5659,7 @@ static int switch_root(int argc, char *argv[], void *userdata) {
if (argc >= 3)
init = argv[2];
else {
- r = parse_env_file("/proc/cmdline", WHITESPACE,
+ r = parse_env_file(NULL, "/proc/cmdline", WHITESPACE,
"init", &cmdline_init,
NULL);
if (r < 0)
@@ -6052,7 +5828,7 @@ static int enable_sysv_units(const char *verb, char **args) {
int r = 0;
#if HAVE_SYSV_COMPAT
- _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_(lookup_paths_free) LookupPaths paths = {};
unsigned f = 0;
/* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
@@ -6199,7 +5975,7 @@ static int mangle_names(char **original_names, char ***mangled_names) {
return log_oom();
}
} else {
- r = unit_name_mangle(*name, UNIT_NAME_NOGLOB, i);
+ r = unit_name_mangle(*name, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, i);
if (r < 0) {
*i = NULL;
strv_free(l);
@@ -6269,10 +6045,11 @@ static int normalize_names(char **names, bool warn_if_path) {
static int unit_exists(LookupPaths *lp, const char *unit) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *path = NULL;
static const struct bus_properties_map property_map[] = {
- { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
- { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state)},
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state)},
{},
};
UnitStatusInfo info = {};
@@ -6290,7 +6067,7 @@ static int unit_exists(LookupPaths *lp, const char *unit) {
if (r < 0)
return r;
- r = bus_map_all_properties(bus, "org.freedesktop.systemd1", path, property_map, &error, &info);
+ r = bus_map_all_properties(bus, "org.freedesktop.systemd1", path, property_map, 0, &error, &m, &info);
if (r < 0)
return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
@@ -6301,7 +6078,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
_cleanup_strv_free_ char **names = NULL;
const char *verb = argv[0];
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
int carries_install_info = -1;
bool ignore_carries_install_info = arg_quiet;
int r;
@@ -6375,7 +6152,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
if (STR_IN_SET(verb, "mask", "unmask")) {
char **name;
- _cleanup_lookup_paths_free_ LookupPaths lp = {};
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
if (r < 0)
@@ -6386,7 +6163,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
if (r == 0)
- log_notice("Unit %s does not exist, proceeding anyway.", *names);
+ log_notice("Unit %s does not exist, proceeding anyway.", *name);
}
}
@@ -6497,7 +6274,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
if (arg_now && STR_IN_SET(argv[0], "enable", "disable", "mask")) {
sd_bus *bus;
- unsigned len, i;
+ size_t len, i;
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
@@ -6527,14 +6304,14 @@ static int add_dependency(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *target = NULL;
const char *verb = argv[0];
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
UnitDependency dep;
int r = 0;
if (!argv[1])
return 0;
- r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &target);
+ r = unit_name_mangle_with_suffix(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, ".target", &target);
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
@@ -6608,7 +6385,7 @@ finish:
static int preset_all(int argc, char *argv[], void *userdata) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
int r;
if (install_client_side()) {
@@ -6663,7 +6440,7 @@ finish:
static int show_installation_targets_client_side(const char *name) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0, i;
+ size_t n_changes = 0, i;
UnitFileFlags flags;
char **p;
int r;
@@ -6719,7 +6496,6 @@ static int show_installation_targets(sd_bus *bus, const char *name) {
}
static int unit_is_enabled(int argc, char *argv[], void *userdata) {
-
_cleanup_strv_free_ char **names = NULL;
bool enabled;
char **name;
@@ -6868,8 +6644,7 @@ static int create_edit_temp_file(const char *new_path, const char *original_path
} else if (r < 0)
return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path);
- *ret_tmp_fn = t;
- t = NULL;
+ *ret_tmp_fn = TAKE_PTR(t);
return 0;
}
@@ -6900,12 +6675,9 @@ static int get_file_to_edit(
return -EEXIST;
}
- *ret_path = run;
- run = NULL;
- } else {
- *ret_path = path;
- path = NULL;
- }
+ *ret_path = TAKE_PTR(run);
+ } else
+ *ret_path = TAKE_PTR(path);
return 0;
}
@@ -6999,7 +6771,7 @@ static int run_editor(char **paths) {
const char **args;
char *editor, **editor_args = NULL;
char **tmp_path, **original_path, *p;
- unsigned n_editor_args = 0, i = 1;
+ size_t n_editor_args = 0, i = 1;
size_t argc;
argc = strv_length(paths)/2 + 1;
@@ -7061,7 +6833,7 @@ static int run_editor(char **paths) {
}
static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
- _cleanup_lookup_paths_free_ LookupPaths lp = {};
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
char **name;
int r;
@@ -7158,6 +6930,17 @@ static int edit(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to expand names: %m");
+ STRV_FOREACH(tmp, names) {
+ r = unit_is_masked(bus, *tmp);
+ if (r < 0)
+ return r;
+
+ if (r > 0) {
+ log_error("Cannot edit %s: unit is masked.", *tmp);
+ return -EINVAL;
+ }
+ }
+
r = find_paths_to_edit(bus, names, &paths);
if (r < 0)
return r;
@@ -7170,8 +6953,8 @@ static int edit(int argc, char *argv[], void *userdata) {
goto end;
STRV_FOREACH_PAIR(original, tmp, paths) {
- /* If the temporary file is empty we ignore it. It's
- * useful if the user wants to cancel its modification
+ /* If the temporary file is empty we ignore it.
+ * This allows the user to cancel the modification.
*/
if (null_or_empty_path(*tmp)) {
log_warning("Editing \"%s\" canceled: temporary file is empty.", *original);
@@ -7213,8 +6996,7 @@ end:
}
static void systemctl_help(void) {
-
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Query or send control commands to the systemd manager.\n\n"
@@ -7349,7 +7131,9 @@ static void systemctl_help(void) {
" switch-root ROOT [INIT] Change to a different root file system\n"
" suspend Suspend the system\n"
" hibernate Hibernate the system\n"
- " hybrid-sleep Hibernate and suspend the system\n",
+ " hybrid-sleep Hibernate and suspend the system\n"
+ " suspend-then-hibernate Suspend the system, wake after a period of\n"
+ " time and put it into hibernate\n",
program_invocation_short_name);
}
@@ -7408,85 +7192,67 @@ static void runlevel_help(void) {
}
static void help_types(void) {
- int i;
-
if (!arg_no_legend)
puts("Available unit types:");
- for (i = 0; i < _UNIT_TYPE_MAX; i++)
- puts(unit_type_to_string(i));
+
+ DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
}
static void help_states(void) {
- int i;
-
if (!arg_no_legend)
puts("Available unit load states:");
- for (i = 0; i < _UNIT_LOAD_STATE_MAX; i++)
- puts(unit_load_state_to_string(i));
+ DUMP_STRING_TABLE(unit_load_state, UnitLoadState, _UNIT_LOAD_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable unit active states:");
- for (i = 0; i < _UNIT_ACTIVE_STATE_MAX; i++)
- puts(unit_active_state_to_string(i));
+ DUMP_STRING_TABLE(unit_active_state, UnitActiveState, _UNIT_ACTIVE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable automount unit substates:");
- for (i = 0; i < _AUTOMOUNT_STATE_MAX; i++)
- puts(automount_state_to_string(i));
+ DUMP_STRING_TABLE(automount_state, AutomountState, _AUTOMOUNT_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable device unit substates:");
- for (i = 0; i < _DEVICE_STATE_MAX; i++)
- puts(device_state_to_string(i));
+ DUMP_STRING_TABLE(device_state, DeviceState, _DEVICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable mount unit substates:");
- for (i = 0; i < _MOUNT_STATE_MAX; i++)
- puts(mount_state_to_string(i));
+ DUMP_STRING_TABLE(mount_state, MountState, _MOUNT_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable path unit substates:");
- for (i = 0; i < _PATH_STATE_MAX; i++)
- puts(path_state_to_string(i));
+ DUMP_STRING_TABLE(path_state, PathState, _PATH_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable scope unit substates:");
- for (i = 0; i < _SCOPE_STATE_MAX; i++)
- puts(scope_state_to_string(i));
+ DUMP_STRING_TABLE(scope_state, ScopeState, _SCOPE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable service unit substates:");
- for (i = 0; i < _SERVICE_STATE_MAX; i++)
- puts(service_state_to_string(i));
+ DUMP_STRING_TABLE(service_state, ServiceState, _SERVICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable slice unit substates:");
- for (i = 0; i < _SLICE_STATE_MAX; i++)
- puts(slice_state_to_string(i));
+ DUMP_STRING_TABLE(slice_state, SliceState, _SLICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable socket unit substates:");
- for (i = 0; i < _SOCKET_STATE_MAX; i++)
- puts(socket_state_to_string(i));
+ DUMP_STRING_TABLE(socket_state, SocketState, _SOCKET_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable swap unit substates:");
- for (i = 0; i < _SWAP_STATE_MAX; i++)
- puts(swap_state_to_string(i));
+ DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable target unit substates:");
- for (i = 0; i < _TARGET_STATE_MAX; i++)
- puts(target_state_to_string(i));
+ DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable timer unit substates:");
- for (i = 0; i < _TIMER_STATE_MAX; i++)
- puts(timer_state_to_string(i));
+ DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
}
static int systemctl_parse_argv(int argc, char *argv[]) {
-
enum {
ARG_FAIL = 0x100,
ARG_REVERSE,
@@ -7778,7 +7544,12 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case 's':
- arg_signal = signal_from_string_try_harder(optarg);
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
+ arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
return -EINVAL;
@@ -7811,6 +7582,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
@@ -7868,6 +7644,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case ARG_PRESET_MODE:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MAX);
+ return 0;
+ }
arg_preset_mode = unit_file_preset_mode_from_string(optarg);
if (arg_preset_mode < 0) {
@@ -7903,11 +7683,15 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
+ if (arg_runtime && STRPTR_IN_SET(argv[optind], "disable", "unmask", "preset", "preset-all")) {
+ log_error("--runtime cannot be used with %s", argv[optind]);
+ return -EINVAL;
+ }
+
return 1;
}
static int halt_parse_argv(int argc, char *argv[]) {
-
enum {
ARG_HELP = 0x100,
ARG_HALT,
@@ -8051,7 +7835,6 @@ static int parse_shutdown_time_spec(const char *t, usec_t *_u) {
}
static int shutdown_parse_argv(int argc, char *argv[]) {
-
enum {
ARG_HELP = 0x100,
ARG_NO_WALL
@@ -8158,7 +7941,6 @@ static int shutdown_parse_argv(int argc, char *argv[]) {
}
static int telinit_parse_argv(int argc, char *argv[]) {
-
enum {
ARG_HELP = 0x100,
ARG_NO_WALL
@@ -8245,7 +8027,6 @@ static int telinit_parse_argv(int argc, char *argv[]) {
}
static int runlevel_parse_argv(int argc, char *argv[]) {
-
enum {
ARG_HELP = 0x100,
};
@@ -8347,7 +8128,6 @@ static int parse_argv(int argc, char *argv[]) {
#if HAVE_SYSV_COMPAT
_pure_ static int action_to_runlevel(void) {
-
static const char table[_ACTION_MAX] = {
[ACTION_HALT] = '0',
[ACTION_POWEROFF] = '0',
@@ -8407,7 +8187,6 @@ static int talk_initctl(void) {
}
static int systemctl_main(int argc, char *argv[]) {
-
static const Verb verbs[] = {
{ "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_units },
{ "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
@@ -8451,6 +8230,7 @@ static int systemctl_main(int argc, char *argv[]) {
{ "suspend", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "hibernate", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "hybrid-sleep", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
+ { "suspend-then-hibernate",VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "default", VERB_ANY, 1, VERB_ONLINE_ONLY, start_special },
{ "rescue", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
{ "emergency", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special },
@@ -8482,7 +8262,6 @@ static int systemctl_main(int argc, char *argv[]) {
}
static int reload_with_fallback(void) {
-
/* First, try systemd via D-Bus. */
if (daemon_reload(0, NULL, NULL) >= 0)
return 0;
@@ -8497,7 +8276,6 @@ static int reload_with_fallback(void) {
}
static int start_with_fallback(void) {
-
/* First, try systemd via D-Bus. */
if (start_unit(0, NULL, NULL) >= 0)
return 0;
@@ -8511,7 +8289,6 @@ static int start_with_fallback(void) {
}
static int halt_now(enum action a) {
-
/* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
* synce'd explicitly in advance. */
if (!arg_no_sync && !arg_dry_run)
@@ -8642,6 +8419,11 @@ static int halt_main(void) {
}
}
+ /* In order to minimize the difference between operation with and
+ * without logind, we explicitly enable non-blocking mode for this,
+ * as logind's shutdown operations are always non-blocking. */
+ arg_no_block = true;
+
if (!arg_dry_run && !arg_force)
return start_with_fallback();
@@ -8782,6 +8564,7 @@ int main(int argc, char*argv[]) {
case ACTION_SUSPEND:
case ACTION_HIBERNATE:
case ACTION_HYBRID_SLEEP:
+ case ACTION_SUSPEND_THEN_HIBERNATE:
case ACTION_EMERGENCY:
case ACTION_DEFAULT:
/* systemctl verbs with no equivalent in the legacy commands.
diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h
index b4400e7b36..7b54d179eb 100644
--- a/src/systemd/_sd-common.h
+++ b/src/systemd/_sd-common.h
@@ -3,9 +3,6 @@
#define foosdcommonhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/meson.build b/src/systemd/meson.build
index 16e4b3540c..5f84439a58 100644
--- a/src/systemd/meson.build
+++ b/src/systemd/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
_systemd_headers = '''
sd-bus.h
@@ -57,11 +42,24 @@ install_headers(
opts = [['c'],
['c', '-ansi'],
- ['c', '-std=iso9899:1990']]
+ ['c', '-std=iso9899:1990'],
+ ['c', '-std=iso9899:2011']]
+
+if cc.has_argument('-std=iso9899:2017')
+ opts += [['c', '-std=iso9899:2017']]
+endif
cxx = find_program('c++', required : false)
if cxx.found()
- opts += [['c++']]
+ opts += [['c++'],
+ ['c++', '-std=c++98'],
+ ['c++', '-std=c++11']]
+ if cc.has_argument('-std=c++14')
+ opts += [['c++', '-std=c++14']]
+ endif
+ if cc.has_argument('-std=c++17')
+ opts += [['c++', '-std=c++17']]
+ endif
endif
foreach header : _systemd_headers
diff --git a/src/systemd/sd-bus-protocol.h b/src/systemd/sd-bus-protocol.h
index 63e3702fbf..acff670f7f 100644
--- a/src/systemd/sd-bus-protocol.h
+++ b/src/systemd/sd-bus-protocol.h
@@ -3,9 +3,6 @@
#define foosdbusprotocolhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
index 425e38e2e2..1268085498 100644
--- a/src/systemd/sd-bus-vtable.h
+++ b/src/systemd/sd-bus-vtable.h
@@ -3,9 +3,6 @@
#define foosdbusvtablehfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index fff6798d0f..54c4b1ca83 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -3,9 +3,6 @@
#define foosdbushfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -111,6 +108,7 @@ typedef int (*sd_bus_property_set_t) (sd_bus *bus, const char *path, const char
typedef int (*sd_bus_object_find_t) (sd_bus *bus, const char *path, const char *interface, void *userdata, void **ret_found, sd_bus_error *ret_error);
typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *prefix, void *userdata, char ***ret_nodes, sd_bus_error *ret_error);
typedef int (*sd_bus_track_handler_t) (sd_bus_track *track, void *userdata);
+typedef void (*sd_bus_destroy_t)(void *userdata);
#include "sd-bus-protocol.h"
#include "sd-bus-vtable.h"
@@ -122,8 +120,11 @@ int sd_bus_default_user(sd_bus **ret);
int sd_bus_default_system(sd_bus **ret);
int sd_bus_open(sd_bus **ret);
+int sd_bus_open_with_description(sd_bus **ret, const char *description);
int sd_bus_open_user(sd_bus **ret);
+int sd_bus_open_user_with_description(sd_bus **ret, const char *description);
int sd_bus_open_system(sd_bus **ret);
+int sd_bus_open_system_with_description(sd_bus **ret, const char *description);
int sd_bus_open_system_remote(sd_bus **ret, const char *host);
int sd_bus_open_system_machine(sd_bus **ret, const char *machine);
@@ -225,6 +226,10 @@ void *sd_bus_slot_get_userdata(sd_bus_slot *slot);
void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata);
int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description);
int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description);
+int sd_bus_slot_get_floating(sd_bus_slot *slot);
+int sd_bus_slot_set_floating(sd_bus_slot *slot, int b);
+int sd_bus_slot_set_destroy_callback(sd_bus_slot *s, sd_bus_destroy_t callback);
+int sd_bus_slot_get_destroy_callback(sd_bus_slot *s, sd_bus_destroy_t *callback);
sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot);
sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *bus);
@@ -477,6 +482,9 @@ const char* sd_bus_track_contains(sd_bus_track *track, const char *name);
const char* sd_bus_track_first(sd_bus_track *track);
const char* sd_bus_track_next(sd_bus_track *track);
+int sd_bus_track_set_destroy_callback(sd_bus_track *s, sd_bus_destroy_t callback);
+int sd_bus_track_get_destroy_callback(sd_bus_track *s, sd_bus_destroy_t *ret);
+
/* Define helpers so that __attribute__((cleanup(sd_bus_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_flush_close_unref);
diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h
index 9772a05dad..59ca6c2785 100644
--- a/src/systemd/sd-daemon.h
+++ b/src/systemd/sd-daemon.h
@@ -3,9 +3,6 @@
#define foosddaemonhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h
index 6ac0b13c0c..3a51c135d4 100644
--- a/src/systemd/sd-device.h
+++ b/src/systemd/sd-device.h
@@ -3,11 +3,6 @@
#define foosddevicehfoo
/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2014-2015 Tom Gundersen <teg@jklm.no>
-
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index 6eb9eb61a8..931b0e890b 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -3,9 +3,7 @@
#define foosddhcpclienthfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
+ Copyright © 2013 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -82,6 +80,7 @@ enum {
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
+ SD_DHCP_OPTION_USER_CLASS = 77,
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
@@ -132,6 +131,11 @@ int sd_dhcp_client_set_iaid_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len);
+int sd_dhcp_client_set_duid(
+ sd_dhcp_client *client,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len);
int sd_dhcp_client_get_client_id(
sd_dhcp_client *client,
uint8_t *type,
@@ -149,6 +153,9 @@ int sd_dhcp_client_set_hostname(
int sd_dhcp_client_set_vendor_class_identifier(
sd_dhcp_client *client,
const char *vci);
+int sd_dhcp_client_set_user_class(
+ sd_dhcp_client *client,
+ const char* const *user_class);
int sd_dhcp_client_get_lease(
sd_dhcp_client *client,
sd_dhcp_lease **ret);
diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h
index 3cc7fcabe3..2a60145f5b 100644
--- a/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/sd-dhcp-lease.h
@@ -3,11 +3,7 @@
#define foosddhcpleasehfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
+ Copyright © 2013 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h
index 9d39e43b98..2d5125db2c 100644
--- a/src/systemd/sd-dhcp-server.h
+++ b/src/systemd/sd-dhcp-server.h
@@ -3,11 +3,7 @@
#define foosddhcpserverhfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2013 Intel Corporation. All rights reserved.
- Copyright (C) 2014 Tom Gundersen
-
+ Copyright © 2013 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index cadb32a051..4f3b2d9e2e 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -3,9 +3,7 @@
#define foosddhcp6clienthfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright © 2014 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h
index 22a5f8ce75..33a32a6dc5 100644
--- a/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/sd-dhcp6-lease.h
@@ -3,10 +3,7 @@
#define foosddhcp6leasehfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
+ Copyright © 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index ec4b7bcf69..7fcae4ac49 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -3,9 +3,6 @@
#define foosdeventhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -24,6 +21,7 @@
#include <inttypes.h>
#include <signal.h>
#include <sys/epoll.h>
+#include <sys/inotify.h>
#include <sys/signalfd.h>
#include <sys/types.h>
#include <time.h>
@@ -78,6 +76,8 @@ typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si,
#else
typedef void* sd_event_child_handler_t;
#endif
+typedef int (*sd_event_inotify_handler_t)(sd_event_source *s, const struct inotify_event *event, void *userdata);
+typedef void (*sd_event_destroy_t)(void *userdata);
int sd_event_default(sd_event **e);
@@ -89,6 +89,7 @@ int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, s
int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata);
int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata);
int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
+int sd_event_add_inotify(sd_event *e, sd_event_source **s, const char *path, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata);
int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
@@ -139,6 +140,9 @@ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec);
int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock);
int sd_event_source_get_signal(sd_event_source *s);
int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid);
+int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret);
+int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback);
+int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret);
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
diff --git a/src/systemd/sd-hwdb.h b/src/systemd/sd-hwdb.h
index fd69aaf3d4..2b0cd7f5e7 100644
--- a/src/systemd/sd-hwdb.h
+++ b/src/systemd/sd-hwdb.h
@@ -3,11 +3,6 @@
#define foosdhwdbhfoo
/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index 67fc595669..b24fd06f01 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -3,9 +3,6 @@
#define foosdid128hfoo
/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-ipv4acd.h b/src/systemd/sd-ipv4acd.h
index 677ae3b216..039ed3c7f2 100644
--- a/src/systemd/sd-ipv4acd.h
+++ b/src/systemd/sd-ipv4acd.h
@@ -3,11 +3,7 @@
#define foosdipv4acdfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
- Copyright (C) 2015 Tom Gundersen
-
+ Copyright © 2014 Axis Communications AB. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
diff --git a/src/systemd/sd-ipv4ll.h b/src/systemd/sd-ipv4ll.h
index c330b0ae9e..71bd4cfe48 100644
--- a/src/systemd/sd-ipv4ll.h
+++ b/src/systemd/sd-ipv4ll.h
@@ -3,9 +3,7 @@
#define foosdipv4llfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Axis Communications AB. All rights reserved.
+ Copyright © 2014 Axis Communications AB. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
index 2a70d5e818..d34c201293 100644
--- a/src/systemd/sd-journal.h
+++ b/src/systemd/sd-journal.h
@@ -3,9 +3,6 @@
#define foosdjournalhfoo
/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h
index 0a76fa6314..d650794cc0 100644
--- a/src/systemd/sd-lldp.h
+++ b/src/systemd/sd-lldp.h
@@ -3,11 +3,6 @@
#define foosdlldphfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Susant Sahani
-
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
index d8e2c6822d..a4f70ef7cd 100644
--- a/src/systemd/sd-login.h
+++ b/src/systemd/sd-login.h
@@ -3,9 +3,6 @@
#define foosdloginhfoo
/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
index 5a3f78bdbc..2adfe16062 100644
--- a/src/systemd/sd-messages.h
+++ b/src/systemd/sd-messages.h
@@ -3,9 +3,6 @@
#define foosdmessageshfoo
/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-ndisc.h b/src/systemd/sd-ndisc.h
index 152114507a..6b6249ca03 100644
--- a/src/systemd/sd-ndisc.h
+++ b/src/systemd/sd-ndisc.h
@@ -3,9 +3,7 @@
#define foosdndiscfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright © 2014 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index e742807e92..51f0fa16b4 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -3,10 +3,6 @@
#define foosdnetlinkhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen <teg@jklm.no>
-
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index 2d48946d2a..c8b7226bca 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -3,11 +3,6 @@
#define foosdnetworkhfoo
/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
- Copyright 2014 Tom Gundersen
-
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
@@ -129,6 +124,14 @@ int sd_network_link_get_llmnr(int ifindex, char **llmnr);
*/
int sd_network_link_get_mdns(int ifindex, char **mdns);
+/* Indicates whether or not DNS-over-TLS should be enabled for the
+ * link.
+ * Possible levels of support: strict, no, opportunistic
+ * Possible return codes:
+ * -ENODATA: networkd is not aware of the link
+ */
+int sd_network_link_get_dns_over_tls(int ifindex, char **dns_over_tls);
+
/* Indicates whether or not DNSSEC should be enabled for the link
* Possible levels of support: yes, no, allow-downgrade
* Possible return codes:
diff --git a/src/systemd/sd-path.h b/src/systemd/sd-path.h
index 2dfc8967b4..65178b63a1 100644
--- a/src/systemd/sd-path.h
+++ b/src/systemd/sd-path.h
@@ -3,9 +3,6 @@
#define foosdpathhfoo
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -74,6 +71,7 @@ enum {
/* Search paths */
SD_PATH_SEARCH_BINARIES,
+ SD_PATH_SEARCH_BINARIES_DEFAULT,
SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED,
diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h
index e319a82dbf..53c507d88c 100644
--- a/src/systemd/sd-radv.h
+++ b/src/systemd/sd-radv.h
@@ -3,9 +3,7 @@
#define foosdradvfoo
/***
- This file is part of systemd.
-
- Copyright (C) 2017 Intel Corporation. All rights reserved.
+ Copyright © 2017 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -43,7 +41,7 @@ _SD_BEGIN_DECLARATIONS;
typedef struct sd_radv sd_radv;
typedef struct sd_radv_prefix sd_radv_prefix;
-/* Router Advertisment */
+/* Router Advertisement */
int sd_radv_new(sd_radv **ret);
sd_radv *sd_radv_ref(sd_radv *ra);
sd_radv *sd_radv_unref(sd_radv *ra);
@@ -64,8 +62,8 @@ int sd_radv_set_managed_information(sd_radv *ra, int managed);
int sd_radv_set_other_information(sd_radv *ra, int other);
int sd_radv_set_preference(sd_radv *ra, unsigned preference);
int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, bool dynamic);
-sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, struct in6_addr *prefix,
- uint8_t prefixlen);
+sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, const struct in6_addr *prefix,
+ unsigned char prefixlen);
int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime,
const struct in6_addr *dns, size_t n_dns);
int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime, char **search_list);
@@ -75,7 +73,7 @@ int sd_radv_prefix_new(sd_radv_prefix **ret);
sd_radv_prefix *sd_radv_prefix_ref(sd_radv_prefix *ra);
sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *ra);
-int sd_radv_prefix_set_prefix(sd_radv_prefix *p, struct in6_addr *in6_addr,
+int sd_radv_prefix_set_prefix(sd_radv_prefix *p, const struct in6_addr *in6_addr,
unsigned char prefixlen);
int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink);
int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p,
diff --git a/src/systemd/sd-resolve.h b/src/systemd/sd-resolve.h
index 14d0cbde04..4c6499815a 100644
--- a/src/systemd/sd-resolve.h
+++ b/src/systemd/sd-resolve.h
@@ -3,9 +3,6 @@
#define foosdresolvehfoo
/***
- This file is part of systemd.
-
- Copyright 2005-2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -43,9 +40,9 @@ typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, co
typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata);
enum {
- SD_RESOLVE_GET_HOST = UINT64_C(1),
- SD_RESOLVE_GET_SERVICE = UINT64_C(2),
- SD_RESOLVE_GET_BOTH = UINT64_C(3),
+ SD_RESOLVE_GET_HOST = 1 << 0,
+ SD_RESOLVE_GET_SERVICE = 1 << 1,
+ SD_RESOLVE_GET_BOTH = SD_RESOLVE_GET_HOST | SD_RESOLVE_GET_SERVICE,
};
int sd_resolve_default(sd_resolve **ret);
diff --git a/src/systemd/sd-utf8.h b/src/systemd/sd-utf8.h
index cd02c6a296..7f2af65049 100644
--- a/src/systemd/sd-utf8.h
+++ b/src/systemd/sd-utf8.h
@@ -3,9 +3,6 @@
#define foosdutf8hfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 43952e5f19..33959d3c11 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -1,28 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
-#include <grp.h>
-#include <gshadow.h>
-#include <pwd.h>
-#include <shadow.h>
#include <utmp.h>
#include "alloc-util.h"
@@ -30,16 +8,18 @@
#include "copy.h"
#include "def.h"
#include "fd-util.h"
-#include "fs-util.h"
#include "fileio-label.h"
#include "format-util.h"
+#include "fs-util.h"
#include "hashmap.h"
+#include "pager.h"
#include "path-util.h"
#include "selinux-util.h"
#include "smack-util.h"
#include "specifier.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
#include "uid-range.h"
#include "user-util.h"
#include "utf8.h"
@@ -51,6 +31,7 @@ typedef enum ItemType {
ADD_MEMBER = 'm',
ADD_RANGE = 'r',
} ItemType;
+
typedef struct Item {
ItemType type;
@@ -78,10 +59,10 @@ typedef struct Item {
} Item;
static char *arg_root = NULL;
+static bool arg_cat_config = false;
static const char *arg_replace = NULL;
static bool arg_inline = false;
-
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d");
+static bool arg_no_pager = false;
static OrderedHashmap *users = NULL, *groups = NULL;
static OrderedHashmap *todo_uids = NULL, *todo_gids = NULL;
@@ -113,8 +94,7 @@ static int load_user_database(void) {
if (r < 0)
return r;
- errno = 0;
- while ((pw = fgetpwent(f))) {
+ while ((r = fgetpwent_sane(f, &pw)) > 0) {
char *n;
int k, q;
@@ -130,20 +110,15 @@ static int load_user_database(void) {
q = hashmap_put(database_uid, UID_TO_PTR(pw->pw_uid), n);
if (q < 0 && q != -EEXIST) {
- if (k < 0)
+ if (k <= 0)
free(n);
return q;
}
- if (q < 0 && k < 0)
+ if (k <= 0 && q <= 0)
free(n);
-
- errno = 0;
}
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
-
- return 0;
+ return r;
}
static int load_group_database(void) {
@@ -182,12 +157,12 @@ static int load_group_database(void) {
q = hashmap_put(database_gid, GID_TO_PTR(gr->gr_gid), n);
if (q < 0 && q != -EEXIST) {
- if (k < 0)
+ if (k <= 0)
free(n);
return q;
}
- if (q < 0 && k < 0)
+ if (k <= 0 && q <= 0)
free(n);
errno = 0;
@@ -232,11 +207,9 @@ static int make_backup(const char *target, const char *x) {
backup = strjoina(x, "-");
/* Copy over the access mask */
- if (fchmod(fileno(dst), st.st_mode & 07777) < 0)
- log_warning_errno(errno, "Failed to change mode on %s: %m", backup);
-
- if (fchown(fileno(dst), st.st_uid, st.st_gid)< 0)
- log_warning_errno(errno, "Failed to change ownership of %s: %m", backup);
+ r = fchmod_and_chown(fileno(dst), st.st_mode & 07777, st.st_uid, st.st_gid);
+ if (r < 0)
+ log_warning_errno(r, "Failed to change access mode or ownership of %s: %m", backup);
ts[0] = st.st_atim;
ts[1] = st.st_mtim;
@@ -287,6 +260,7 @@ static int putgrent_with_members(const struct group *gr, FILE *group) {
if (added) {
struct group t;
+ int r;
strv_uniq(l);
strv_sort(l);
@@ -294,19 +268,12 @@ static int putgrent_with_members(const struct group *gr, FILE *group) {
t = *gr;
t.gr_mem = l;
- errno = 0;
- if (putgrent(&t, group) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return 1;
+ r = putgrent_sane(&t, group);
+ return r < 0 ? r : 1;
}
}
- errno = 0;
- if (putgrent(gr, group) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return 0;
+ return putgrent_sane(gr, group);
}
#if ENABLE_GSHADOW
@@ -338,6 +305,7 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) {
if (added) {
struct sgrp t;
+ int r;
strv_uniq(l);
strv_sort(l);
@@ -345,19 +313,12 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) {
t = *sg;
t.sg_mem = l;
- errno = 0;
- if (putsgent(&t, gshadow) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return 1;
+ r = putsgent_sane(&t, gshadow);
+ return r < 0 ? r : 1;
}
}
- errno = 0;
- if (putsgent(sg, gshadow) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return 0;
+ return putsgent_sane(sg, gshadow);
}
#endif
@@ -367,13 +328,7 @@ static int sync_rights(FILE *from, FILE *to) {
if (fstat(fileno(from), &st) < 0)
return -errno;
- if (fchmod(fileno(to), st.st_mode & 07777) < 0)
- return -errno;
-
- if (fchown(fileno(to), st.st_uid, st.st_gid) < 0)
- return -errno;
-
- return 0;
+ return fchmod_and_chown(fileno(to), st.st_mode & 07777, st.st_uid, st.st_gid);
}
static int rename_and_apply_smack(const char *temp_path, const char *dest_path) {
@@ -415,8 +370,7 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
if (r < 0)
return r;
- errno = 0;
- while ((pw = fgetpwent(original))) {
+ while ((r = fgetpwent_sane(original, &pw)) > 0) {
i = ordered_hashmap_get(users, pw->pw_name);
if (i && i->todo_user) {
@@ -429,19 +383,16 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
return -EEXIST;
}
- errno = 0;
-
/* Make sure we keep the NIS entries (if any) at the end. */
if (IN_SET(pw->pw_name[0], '+', '-'))
break;
- if (putpwent(pw, passwd) < 0)
- return errno ? -errno : -EIO;
-
- errno = 0;
+ r = putpwent_sane(pw, passwd);
+ if (r < 0)
+ return r;
}
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
+ if (r < 0)
+ return r;
} else {
if (errno != ENOENT)
@@ -468,32 +419,31 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
.pw_shell = i->shell ?: (char*) default_shell(i->uid),
};
- errno = 0;
- if (putpwent(&n, passwd) != 0)
- return errno ? -errno : -EIO;
+ r = putpwent_sane(&n, passwd);
+ if (r < 0)
+ return r;
}
- errno = 0;
/* Append the remaining NIS entries if any */
while (pw) {
- errno = 0;
- if (putpwent(pw, passwd) < 0)
- return errno ? -errno : -EIO;
+ r = putpwent_sane(pw, passwd);
+ if (r < 0)
+ return r;
- errno = 0;
- pw = fgetpwent(original);
+ r = fgetpwent_sane(original, &pw);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
}
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
r = fflush_and_check(passwd);
if (r < 0)
return r;
- *tmpfile = passwd;
- *tmpfile_path = passwd_tmp;
- passwd = NULL;
- passwd_tmp = NULL;
+ *tmpfile = TAKE_PTR(passwd);
+ *tmpfile_path = TAKE_PTR(passwd_tmp);
+
return 0;
}
@@ -522,8 +472,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
if (r < 0)
return r;
- errno = 0;
- while ((sp = fgetspent(original))) {
+ while ((r = fgetspent_sane(original, &sp)) > 0) {
i = ordered_hashmap_get(users, sp->sp_namp);
if (i && i->todo_user) {
@@ -536,19 +485,16 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
ordered_hashmap_remove(todo_uids, UID_TO_PTR(i->uid));
}
- errno = 0;
-
/* Make sure we keep the NIS entries (if any) at the end. */
if (IN_SET(sp->sp_namp[0], '+', '-'))
break;
- if (putspent(sp, shadow) < 0)
- return errno ? -errno : -EIO;
-
- errno = 0;
+ r = putspent_sane(sp, shadow);
+ if (r < 0)
+ return r;
}
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
+ if (r < 0)
+ return r;
} else {
if (errno != ENOENT)
@@ -570,20 +516,22 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
.sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
};
- errno = 0;
- if (putspent(&n, shadow) != 0)
- return errno ? -errno : -EIO;
+ r = putspent_sane(&n, shadow);
+ if (r < 0)
+ return r;
}
- errno = 0;
/* Append the remaining NIS entries if any */
while (sp) {
- errno = 0;
- if (putspent(sp, shadow) < 0)
- return errno ? -errno : -EIO;
+ r = putspent_sane(sp, shadow);
+ if (r < 0)
+ return r;
- errno = 0;
- sp = fgetspent(original);
+ r = fgetspent_sane(original, &sp);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
}
if (!IN_SET(errno, 0, ENOENT))
return -errno;
@@ -592,10 +540,9 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
if (r < 0)
return r;
- *tmpfile = shadow;
- *tmpfile_path = shadow_tmp;
- shadow = NULL;
- shadow_tmp = NULL;
+ *tmpfile = TAKE_PTR(shadow);
+ *tmpfile_path = TAKE_PTR(shadow_tmp);
+
return 0;
}
@@ -622,8 +569,7 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
if (r < 0)
return r;
- errno = 0;
- while ((gr = fgetgrent(original))) {
+ while ((r = fgetgrent_sane(original, &gr)) > 0) {
/* Safety checks against name and GID collisions. Normally,
* this should be unnecessary, but given that we look at the
* entries anyway here, let's make an extra verification
@@ -640,8 +586,6 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
return -EEXIST;
}
- errno = 0;
-
/* Make sure we keep the NIS entries (if any) at the end. */
if (IN_SET(gr->gr_name[0], '+', '-'))
break;
@@ -651,11 +595,9 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
return r;
if (r > 0)
group_changed = true;
-
- errno = 0;
}
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
+ if (r < 0)
+ return r;
} else {
if (errno != ENOENT)
@@ -677,29 +619,27 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
group_changed = true;
}
- errno = 0;
/* Append the remaining NIS entries if any */
while (gr) {
- errno = 0;
- if (putgrent(gr, group) != 0)
- return errno > 0 ? -errno : -EIO;
+ r = putgrent_sane(gr, group);
+ if (r < 0)
+ return r;
- errno = 0;
- gr = fgetgrent(original);
+ r = fgetgrent_sane(original, &gr);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
}
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
r = fflush_sync_and_check(group);
if (r < 0)
return r;
if (group_changed) {
- *tmpfile = group;
- *tmpfile_path = group_tmp;
- group = NULL;
- group_tmp = NULL;
+ *tmpfile = TAKE_PTR(group);
+ *tmpfile_path = TAKE_PTR(group_tmp);
}
return 0;
}
@@ -728,8 +668,7 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch
if (r < 0)
return r;
- errno = 0;
- while ((sg = fgetsgent(original))) {
+ while ((r = fgetsgent_sane(original, &sg)) > 0) {
i = ordered_hashmap_get(groups, sg->sg_namp);
if (i && i->todo_group) {
@@ -742,11 +681,9 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch
return r;
if (r > 0)
group_changed = true;
-
- errno = 0;
}
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
+ if (r < 0)
+ return r;
} else {
if (errno != ENOENT)
@@ -773,10 +710,8 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch
return r;
if (group_changed) {
- *tmpfile = gshadow;
- *tmpfile_path = gshadow_tmp;
- gshadow = NULL;
- gshadow_tmp = NULL;
+ *tmpfile = TAKE_PTR(gshadow);
+ *tmpfile_path = TAKE_PTR(gshadow_tmp);
}
return 0;
#else
@@ -1414,18 +1349,20 @@ static bool item_equal(Item *a, Item *b) {
static int parse_line(const char *fname, unsigned line, const char *buffer) {
static const Specifier specifier_table[] = {
- { 'm', specifier_machine_id, NULL },
- { 'b', specifier_boot_id, NULL },
- { 'H', specifier_host_name, NULL },
+ { 'm', specifier_machine_id, NULL },
+ { 'b', specifier_boot_id, NULL },
+ { 'H', specifier_host_name, NULL },
{ 'v', specifier_kernel_release, NULL },
+ { 'T', specifier_tmp_dir, NULL },
+ { 'V', specifier_var_tmp_dir, NULL },
{}
};
_cleanup_free_ char *action = NULL,
*name = NULL, *resolved_name = NULL,
*id = NULL, *resolved_id = NULL,
- *description = NULL,
- *home = NULL,
+ *description = NULL, *resolved_description = NULL,
+ *home = NULL, *resolved_home = NULL,
*shell, *resolved_shell = NULL;
_cleanup_(item_freep) Item *i = NULL;
Item *existing;
@@ -1499,8 +1436,14 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
description = mfree(description);
if (description) {
- if (!valid_gecos(description)) {
- log_error("[%s:%u] '%s' is not a valid GECOS field.", fname, line, description);
+ r = specifier_printf(description, specifier_table, NULL, &resolved_description);
+ if (r < 0) {
+ log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, description);
+ return r;
+ }
+
+ if (!valid_gecos(resolved_description)) {
+ log_error("[%s:%u] '%s' is not a valid GECOS field.", fname, line, resolved_description);
return -EINVAL;
}
}
@@ -1510,8 +1453,14 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
home = mfree(home);
if (home) {
- if (!valid_home(home)) {
- log_error("[%s:%u] '%s' is not a valid home directory field.", fname, line, home);
+ r = specifier_printf(home, specifier_table, NULL, &resolved_home);
+ if (r < 0) {
+ log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, home);
+ return r;
+ }
+
+ if (!valid_home(resolved_home)) {
+ log_error("[%s:%u] '%s' is not a valid home directory field.", fname, line, resolved_home);
return -EINVAL;
}
}
@@ -1533,7 +1482,6 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
}
}
-
switch (action[0]) {
case ADD_RANGE:
@@ -1640,10 +1588,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
if (resolved_id) {
if (path_is_absolute(resolved_id)) {
- i->uid_path = resolved_id;
- resolved_id = NULL;
-
- path_kill_slashes(i->uid_path);
+ i->uid_path = TAKE_PTR(resolved_id);
+ path_simplify(i->uid_path, false);
} else {
_cleanup_free_ char *uid = NULL, *gid = NULL;
if (split_pair(resolved_id, ":", &uid, &gid) == 0) {
@@ -1663,14 +1609,9 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
}
}
- i->description = description;
- description = NULL;
-
- i->home = home;
- home = NULL;
-
- i->shell = resolved_shell;
- resolved_shell = NULL;
+ i->description = TAKE_PTR(resolved_description);
+ i->home = TAKE_PTR(resolved_home);
+ i->shell = TAKE_PTR(resolved_shell);
h = users;
break;
@@ -1698,10 +1639,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
if (resolved_id) {
if (path_is_absolute(resolved_id)) {
- i->gid_path = resolved_id;
- resolved_id = NULL;
-
- path_kill_slashes(i->gid_path);
+ i->gid_path = TAKE_PTR(resolved_id);
+ path_simplify(i->gid_path, false);
} else {
r = parse_gid(resolved_id, &i->gid);
if (r < 0)
@@ -1719,8 +1658,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
}
i->type = action[0];
- i->name = resolved_name;
- resolved_name = NULL;
+ i->name = TAKE_PTR(resolved_name);
existing = ordered_hashmap_get(h, i->name);
if (existing) {
@@ -1752,7 +1690,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
if (streq(fn, "-"))
f = stdin;
else {
- r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &rf);
+ r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf);
if (r < 0) {
if (ignore_enoent && r == -ENOENT)
return 0;
@@ -1808,14 +1746,29 @@ static void free_database(Hashmap *by_name, Hashmap *by_id) {
hashmap_free(by_id);
}
+static int cat_config(void) {
+ _cleanup_strv_free_ char **files = NULL;
+ int r;
+
+ r = conf_files_list_with_replacement(arg_root, CONF_PATHS_STRV("sysusers.d"), arg_replace, &files, NULL);
+ if (r < 0)
+ return r;
+
+ (void) pager_open(arg_no_pager, false);
+
+ return cat_files(NULL, files, 0);
+}
+
static void help(void) {
printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
"Creates system user accounts.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --cat-config Show configuration files\n"
" --root=PATH Operate on an alternate filesystem root\n"
" --replace=PATH Treat arguments as replacement for PATH\n"
" --inline Treat arguments as configuration lines\n"
+ " --no-pager Do not pipe output into a pager\n"
, program_invocation_short_name);
}
@@ -1823,17 +1776,21 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
+ ARG_CAT_CONFIG,
ARG_ROOT,
ARG_REPLACE,
ARG_INLINE,
+ ARG_NO_PAGER,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "root", required_argument, NULL, ARG_ROOT },
- { "replace", required_argument, NULL, ARG_REPLACE },
- { "inline", no_argument, NULL, ARG_INLINE },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
+ { "root", required_argument, NULL, ARG_ROOT },
+ { "replace", required_argument, NULL, ARG_REPLACE },
+ { "inline", no_argument, NULL, ARG_INLINE },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
@@ -1853,6 +1810,10 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_VERSION:
return version();
+ case ARG_CAT_CONFIG:
+ arg_cat_config = true;
+ break;
+
case ARG_ROOT:
r = parse_path_argument_and_warn(optarg, true, &arg_root);
if (r < 0)
@@ -1873,6 +1834,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_inline = true;
break;
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
case '?':
return -EINVAL;
@@ -1880,6 +1845,11 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached("Unhandled option");
}
+ if (arg_replace && arg_cat_config) {
+ log_error("Option --replace= is not supported with --cat-config");
+ return -EINVAL;
+ }
+
if (arg_replace && optind >= argc) {
log_error("When --replace= is given, some configuration items must be specified");
return -EINVAL;
@@ -1908,25 +1878,15 @@ static int parse_arguments(char **args) {
return 0;
}
-static int read_config_files(const char* dirs, char **args) {
+static int read_config_files(char **args) {
_cleanup_strv_free_ char **files = NULL;
_cleanup_free_ char *p = NULL;
char **f;
int r;
- r = conf_files_list_nulstr(&files, ".conf", arg_root, 0, dirs);
+ r = conf_files_list_with_replacement(arg_root, CONF_PATHS_STRV("sysusers.d"), arg_replace, &files, &p);
if (r < 0)
- return log_error_errno(r, "Failed to enumerate sysusers.d files: %m");
-
- if (arg_replace) {
- r = conf_files_insert_nulstr(&files, arg_root, dirs, arg_replace);
- if (r < 0)
- return log_error_errno(r, "Failed to extend sysusers.d file list: %m");
-
- p = path_join(arg_root, arg_replace, NULL);
- if (!p)
- return log_oom();
- }
+ return r;
STRV_FOREACH(f, files)
if (p && path_equal(*f, p)) {
@@ -1946,7 +1906,6 @@ static int read_config_files(const char* dirs, char **args) {
}
int main(int argc, char *argv[]) {
-
_cleanup_close_ int lock = -1;
Iterator iterator;
int r;
@@ -1961,6 +1920,11 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
+ if (arg_cat_config) {
+ r = cat_config();
+ goto finish;
+ }
+
umask(0022);
r = mac_selinux_init();
@@ -1976,7 +1940,7 @@ int main(int argc, char *argv[]) {
* read configuration and execute it.
*/
if (arg_replace || optind >= argc)
- r = read_config_files(conf_file_dirs, argv + optind);
+ r = read_config_files(argv + optind);
else
r = parse_arguments(argv + optind);
if (r < 0)
@@ -2024,16 +1988,18 @@ int main(int argc, char *argv[]) {
}
ORDERED_HASHMAP_FOREACH(i, groups, iterator)
- process_item(i);
+ (void) process_item(i);
ORDERED_HASHMAP_FOREACH(i, users, iterator)
- process_item(i);
+ (void) process_item(i);
r = write_files();
if (r < 0)
log_error_errno(r, "Failed to write files: %m");
finish:
+ pager_close();
+
ordered_hashmap_free_with_destructor(groups, item_free);
ordered_hashmap_free_with_destructor(users, item_free);
@@ -2049,6 +2015,8 @@ finish:
free_database(database_user, database_uid);
free_database(database_group, database_gid);
+ free(uid_range);
+
free(arg_root);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index 087ba08559..2b1e267c08 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -1,24 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Thomas H.P. Andersen
- Copyright 2010 Lennart Poettering
- Copyright 2011 Michal Schmidt
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
@@ -240,7 +220,7 @@ static char *sysv_translate_name(const char *name) {
if (res)
*res = 0;
- if (unit_name_mangle(c, UNIT_NAME_NOGLOB, &res) < 0)
+ if (unit_name_mangle(c, 0, &res) < 0)
return NULL;
return res;
@@ -741,8 +721,7 @@ static int acquire_search_path(const char *def, const char *envvar, char ***ret)
if (!path_strv_resolve_uniq(l, NULL))
return log_oom();
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
return 0;
}
@@ -810,9 +789,8 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
return log_oom();
service->sysv_start_priority = -1;
- service->name = name;
- service->path = fpath;
- name = fpath = NULL;
+ service->name = TAKE_PTR(name);
+ service->path = TAKE_PTR(fpath);
r = hashmap_put(all_services, service->name, service);
if (r < 0)
@@ -937,7 +915,7 @@ finish:
int main(int argc, char *argv[]) {
_cleanup_(free_sysvstub_hashmapp) Hashmap *all_services = NULL;
- _cleanup_lookup_paths_free_ LookupPaths lp = {};
+ _cleanup_(lookup_paths_free) LookupPaths lp = {};
SysvStub *service;
Iterator j;
int r;
diff --git a/src/test/meson.build b/src/test/meson.build
index 4f28ef8722..7da7e3a22c 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
awkscript = 'test-hashmap-ordered.awk'
test_hashmap_ordered_c = custom_target(
@@ -191,6 +176,10 @@ tests += [
[],
[]],
+ [['src/test/test-format-table.c'],
+ [],
+ []],
+
[['src/test/test-ratelimit.c'],
[],
[]],
@@ -251,6 +240,10 @@ tests += [
[],
[]],
+ [['src/test/test-os-util.c'],
+ [],
+ []],
+
[['src/test/test-escape.c'],
[],
[]],
@@ -566,7 +559,8 @@ tests += [
libseccomp,
libselinux,
libmount,
- libblkid]],
+ libblkid],
+ '', 'timeout=360'],
[['src/test/test-siphash24.c'],
[],
@@ -652,6 +646,18 @@ tests += [
[],
[libdl],
'', 'manual'],
+
+ [['src/test/test-umount.c',
+ 'src/core/mount-setup.c',
+ 'src/core/mount-setup.h',
+ 'src/core/umount.c',
+ 'src/core/umount.h'],
+ [],
+ [libmount]],
+
+ [['src/test/test-bus-util.c'],
+ [],
+ []],
]
############################################################
@@ -717,6 +723,13 @@ tests += [
libxz,
liblz4]],
+ [['src/journal/test-journal-config.c'],
+ [libjournal_core,
+ libshared],
+ [libxz,
+ liblz4,
+ libselinux]],
+
[['src/journal/test-journal-verify.c'],
[libjournal_core,
libshared],
diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c
index 70ffdbc519..81eb40444b 100644
--- a/src/test/test-acl-util.c
+++ b/src/test/test-acl-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 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 <fcntl.h>
#include <stdlib.h>
diff --git a/src/test/test-af-list.c b/src/test/test-af-list.c
index 2d42dc2c54..8806744edb 100644
--- a/src/test/test-af-list.c
+++ b/src/test/test-af-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2015 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
#include <sys/socket.h>
diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c
index ed598e106c..40c32d7114 100644
--- a/src/test/test-alloc-util.c
+++ b/src/test/test-alloc-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdint.h>
@@ -70,9 +52,30 @@ static void test_memdup_multiply_and_greedy_realloc(void) {
assert_se(p[i] == 0);
}
+static void test_bool_assign(void) {
+ bool b, c, *cp = &c, d, e, f, g, h;
+
+ b = 123;
+ *cp = -11;
+ d = 0xF & 0xFF;
+ e = b & d;
+ f = 0x0;
+ g = cp; /* cast from pointer */
+ h = NULL; /* cast from pointer */
+
+ assert(b);
+ assert(c);
+ assert(d);
+ assert(e);
+ assert(!f);
+ assert(g);
+ assert(!h);
+}
+
int main(int argc, char *argv[]) {
test_alloca();
test_memdup_multiply_and_greedy_realloc();
+ test_bool_assign();
return 0;
}
diff --git a/src/test/test-architecture.c b/src/test/test-architecture.c
index 586d54b140..6bc0a28a42 100644
--- a/src/test/test-architecture.c
+++ b/src/test/test-architecture.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 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 "architecture.h"
#include "log.h"
diff --git a/src/test/test-arphrd-list.c b/src/test/test-arphrd-list.c
index e503582820..10cd9ebab9 100644
--- a/src/test/test-arphrd-list.c
+++ b/src/test/test-arphrd-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2015 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if_arp.h>
#include <string.h>
diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c
index 562a774531..ffd6da80fe 100644
--- a/src/test/test-ask-password-api.c
+++ b/src/test/test-ask-password-api.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "ask-password-api.h"
diff --git a/src/test/test-async.c b/src/test/test-async.c
index 87906b2e25..7c7dfe62da 100644
--- a/src/test/test-async.c
+++ b/src/test/test-async.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
diff --git a/src/test/test-barrier.c b/src/test/test-barrier.c
index 1001cc2a5a..d2afd92f63 100644
--- a/src/test/test-barrier.c
+++ b/src/test/test-barrier.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 David Herrmann <dh.herrmann@gmail.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/>.
-***/
/*
* IPC barrier tests
diff --git a/src/test/test-bitmap.c b/src/test/test-bitmap.c
index fa38056126..f73d36e255 100644
--- a/src/test/test-bitmap.c
+++ b/src/test/test-bitmap.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "bitmap.h"
diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c
index 37e799d783..ef39304b9f 100644
--- a/src/test/test-boot-timestamps.c
+++ b/src/test/test-boot-timestamps.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 "acpi-fpdt.h"
#include "boot-timestamps.h"
diff --git a/src/test/test-bpf.c b/src/test/test-bpf.c
index 6ca2be41b0..4d89bd46d3 100644
--- a/src/test/test-bpf.c
+++ b/src/test/test-bpf.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <linux/libbpf.h>
#include <string.h>
@@ -41,7 +23,7 @@ int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
CGroupContext *cc = NULL;
_cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
- Manager *m = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
Unit *u;
char log_buf[65535];
int r;
@@ -128,11 +110,9 @@ int main(int argc, char *argv[]) {
unit_dump(u, stdout, NULL);
r = bpf_firewall_compile(u);
- if (IN_SET(r, -ENOTTY, -ENOSYS, -EPERM )) {
+ if (IN_SET(r, -ENOTTY, -ENOSYS, -EPERM ))
/* Kernel doesn't support the necessary bpf bits, or masked out via seccomp? */
- manager_free(m);
return EXIT_TEST_SKIP;
- }
assert_se(r >= 0);
assert(u->ip_bpf_ingress);
@@ -167,7 +147,5 @@ int main(int argc, char *argv[]) {
assert_se(SERVICE(u)->exec_command[SERVICE_EXEC_START]->command_next->exec_status.code != CLD_EXITED ||
SERVICE(u)->exec_command[SERVICE_EXEC_START]->command_next->exec_status.status != EXIT_SUCCESS);
- manager_free(m);
-
return 0;
}
diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c
index 645594ce6c..5e5638cd72 100644
--- a/src/test/test-btrfs.c
+++ b/src/test/test-btrfs.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
diff --git a/src/test/test-bus-util.c b/src/test/test-bus-util.c
new file mode 100644
index 0000000000..791b3928fe
--- /dev/null
+++ b/src/test/test-bus-util.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-util.h"
+#include "log.h"
+
+static void test_name_async(unsigned n_messages) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ int r;
+ unsigned i;
+
+ log_info("/* %s (%u) */", __func__, n_messages);
+
+ r = bus_open_system_watch_bind_with_description(&bus, "test-bus");
+ if (r < 0) {
+ log_error_errno(r, "Failed to connect to bus: %m");
+ return;
+ }
+
+ r = bus_request_name_async_may_reload_dbus(bus, NULL, "org.freedesktop.systemd.test-bus-util", 0, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to request name: %m");
+ return;
+ }
+
+ for (i = 0; i < n_messages; i++) {
+ r = sd_bus_process(bus, NULL);
+ log_debug("stage %u: sd_bus_process returned %d", i, r);
+ if (r < 0) {
+ log_notice_errno(r, "Processing failed: %m");
+ return;
+ }
+
+ if (r > 0 && i + 1 < n_messages)
+ (void) sd_bus_wait(bus, USEC_PER_SEC / 3);
+ }
+}
+
+static int callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ return 1;
+}
+
+static void destroy_callback(void *userdata) {
+ int *n_called = userdata;
+
+ (*n_called) ++;
+}
+
+static void test_destroy_callback(void) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ sd_bus_slot *slot = NULL;
+ sd_bus_destroy_t t;
+
+ int r, n_called = 0;
+
+ log_info("/* %s */", __func__);
+
+ r = bus_open_system_watch_bind_with_description(&bus, "test-bus");
+ if (r < 0) {
+ log_error_errno(r, "Failed to connect to bus: %m");
+ return;
+ }
+
+ r = sd_bus_request_name_async(bus, &slot, "org.freedesktop.systemd.test-bus-util", 0, callback, &n_called);
+ assert(r == 1);
+
+ assert_se(sd_bus_slot_get_destroy_callback(slot, NULL) == 0);
+ assert_se(sd_bus_slot_get_destroy_callback(slot, &t) == 0);
+
+ assert_se(sd_bus_slot_set_destroy_callback(slot, destroy_callback) == 0);
+ assert_se(sd_bus_slot_get_destroy_callback(slot, NULL) == 1);
+ assert_se(sd_bus_slot_get_destroy_callback(slot, &t) == 1);
+ assert_se(t == destroy_callback);
+
+ /* Force cleanup so we can look at n_called */
+ assert(n_called == 0);
+ sd_bus_slot_unref(slot);
+ assert(n_called == 1);
+}
+
+int main(int argc, char **argv) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_name_async(0);
+ test_name_async(20);
+ test_destroy_callback();
+
+ return 0;
+}
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 1a95b60740..10c9f63b9b 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
@@ -259,6 +241,7 @@ int main(int argc, char* argv[]) {
assert_se(calendar_spec_from_string("00:00/60", &c) < 0);
assert_se(calendar_spec_from_string("00:00:2300", &c) < 0);
assert_se(calendar_spec_from_string("00:00:18446744073709551615", &c) < 0);
+ assert_se(calendar_spec_from_string("@88588582097858858", &c) == -ERANGE);
test_timestamp();
test_hourly_bug_4031();
diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c
index 935567cc23..de5fa729cc 100644
--- a/src/test/test-cap-list.c
+++ b/src/test/test-cap-list.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/prctl.h>
diff --git a/src/test/test-capability.c b/src/test/test-capability.c
index 10cddaf552..af6d808b6d 100644
--- a/src/test/test-capability.c
+++ b/src/test/test-capability.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/in.h>
#include <pwd.h>
diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
index 10ae523b52..d65959edf1 100644
--- a/src/test/test-cgroup-mask.c
+++ b/src/test/test-cgroup-mask.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 David Strauss
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 David Strauss
***/
#include <stdio.h>
@@ -30,10 +15,8 @@
static int test_cgroup_mask(void) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
- Manager *m = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep;
- FILE *serial = NULL;
- FDSet *fdset = NULL;
int r;
r = enter_cgroup_subroot();
@@ -45,7 +28,7 @@ static int test_cgroup_mask(void) {
/* Prepare the manager. */
assert_se(set_unit_path(get_testdata_dir("")) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
- r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
+ r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m);
if (IN_SET(r, -EPERM, -EACCES)) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;
@@ -63,19 +46,14 @@ static int test_cgroup_mask(void) {
m->default_tasks_max = (uint64_t) -1;
assert_se(r >= 0);
- assert_se(manager_startup(m, serial, fdset) >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
/* Load units and verify hierarchy. */
- assert_se(manager_load_unit(m, "parent.slice", NULL, NULL, &parent) >= 0);
- assert_se(manager_load_unit(m, "son.service", NULL, NULL, &son) >= 0);
- assert_se(manager_load_unit(m, "daughter.service", NULL, NULL, &daughter) >= 0);
- assert_se(manager_load_unit(m, "grandchild.service", NULL, NULL, &grandchild) >= 0);
- assert_se(manager_load_unit(m, "parent-deep.slice", NULL, NULL, &parent_deep) >= 0);
- assert_se(parent->load_state == UNIT_LOADED);
- assert_se(son->load_state == UNIT_LOADED);
- assert_se(daughter->load_state == UNIT_LOADED);
- assert_se(grandchild->load_state == UNIT_LOADED);
- assert_se(parent_deep->load_state == UNIT_LOADED);
+ assert_se(manager_load_startable_unit_or_warn(m, "parent.slice", NULL, &parent) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "son.service", NULL, &son) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "daughter.service", NULL, &daughter) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "grandchild.service", NULL, &grandchild) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "parent-deep.slice", NULL, &parent_deep) >= 0);
assert_se(UNIT_DEREF(son->slice) == parent);
assert_se(UNIT_DEREF(daughter->slice) == parent);
assert_se(UNIT_DEREF(parent_deep->slice) == parent);
@@ -114,8 +92,6 @@ static int test_cgroup_mask(void) {
assert_se(unit_get_target_mask(parent) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
assert_se(unit_get_target_mask(root) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
- manager_free(m);
-
return 0;
}
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index 9ef7c97c74..d49356315e 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "build.h"
@@ -266,13 +248,18 @@ static void test_controller_is_valid(void) {
static void test_slice_to_path_one(const char *unit, const char *path, int error) {
_cleanup_free_ char *ret = NULL;
+ int r;
+
+ log_info("unit: %s", unit);
- assert_se(cg_slice_to_path(unit, &ret) == error);
+ r = cg_slice_to_path(unit, &ret);
+ log_info("actual: %s / %d", strnull(ret), r);
+ log_info("expect: %s / %d", strnull(path), error);
+ assert_se(r == 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);
@@ -286,6 +273,15 @@ static void test_slice_to_path(void) {
test_slice_to_path_one("foo.slice/foo--bar.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);
+
+ test_slice_to_path_one("foobar@.slice", NULL, -EINVAL);
+ test_slice_to_path_one("foobar@waldo.slice", NULL, -EINVAL);
+ test_slice_to_path_one("foobar@waldo.service", 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("foo@-.slice", NULL, -EINVAL);
+ test_slice_to_path_one("foo@@bar.slice", NULL, -EINVAL);
+ test_slice_to_path_one("foo.slice/foo@@bar.slice", NULL, -EINVAL);
}
static void test_shift_path_one(const char *raw, const char *root, const char *shifted) {
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
index b2440fc3a9..9211c996ac 100644
--- a/src/test/test-cgroup.c
+++ b/src/test/test-cgroup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
#include <unistd.h>
diff --git a/src/test/test-clock.c b/src/test/test-clock.c
index 11773cc180..50e9b7756f 100644
--- a/src/test/test-clock.c
+++ b/src/test/test-clock.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright (C) 2016 Canonical Ltd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Canonical Ltd.
***/
#include <unistd.h>
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
index ad64a2bb36..7ce6ee80ea 100644
--- a/src/test/test-condition.c
+++ b/src/test/test-condition.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
#include <sys/types.h>
@@ -31,6 +13,7 @@
#include "audit-util.h"
#include "cgroup-util.h"
#include "condition.h"
+#include "efivars.h"
#include "hostname-util.h"
#include "id128-util.h"
#include "ima-util.h"
@@ -41,6 +24,7 @@
#include "smack-util.h"
#include "string-util.h"
#include "strv.h"
+#include "tomoyo-util.h"
#include "user-util.h"
#include "util.h"
#include "virt.h"
@@ -447,14 +431,19 @@ static void test_condition_test_security(void) {
assert_se(condition_test(condition) != mac_selinux_use());
condition_free(condition);
- condition = condition_new(CONDITION_SECURITY, "ima", false, false);
+ condition = condition_new(CONDITION_SECURITY, "apparmor", false, false);
assert_se(condition);
- assert_se(condition_test(condition) == use_ima());
+ assert_se(condition_test(condition) == mac_apparmor_use());
condition_free(condition);
- condition = condition_new(CONDITION_SECURITY, "apparmor", false, false);
+ condition = condition_new(CONDITION_SECURITY, "tomoyo", false, false);
assert_se(condition);
- assert_se(condition_test(condition) == mac_apparmor_use());
+ assert_se(condition_test(condition) == mac_tomoyo_use());
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_SECURITY, "ima", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition) == use_ima());
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "smack", false, false);
@@ -466,6 +455,23 @@ static void test_condition_test_security(void) {
assert_se(condition);
assert_se(condition_test(condition) == use_audit());
condition_free(condition);
+
+ condition = condition_new(CONDITION_SECURITY, "uefi-secureboot", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition) == is_efi_secure_boot());
+ condition_free(condition);
+}
+
+static void print_securities(void) {
+ log_info("------ enabled security technologies ------");
+ log_info("SELinux: %s", yes_no(mac_selinux_use()));
+ log_info("AppArmor: %s", yes_no(mac_apparmor_use()));
+ log_info("Tomoyo: %s", yes_no(mac_tomoyo_use()));
+ log_info("IMA: %s", yes_no(use_ima()));
+ log_info("SMACK: %s", yes_no(mac_smack_use()));
+ log_info("Audit: %s", yes_no(use_audit()));
+ log_info("UEFI secure boot: %s", yes_no(is_efi_secure_boot()));
+ log_info("-------------------------------------------");
}
static void test_condition_test_virtualization(void) {
@@ -621,7 +627,7 @@ static void test_condition_test_group(void) {
ngroups_max = sysconf(_SC_NGROUPS_MAX);
assert(ngroups_max > 0);
- gids = alloca(sizeof(gid_t) * ngroups_max);
+ gids = newa(gid_t, ngroups_max);
ngroups = getgroups(ngroups_max, gids);
assert(ngroups >= 0);
@@ -681,6 +687,7 @@ int main(int argc, char *argv[]) {
test_condition_test_kernel_version();
test_condition_test_null();
test_condition_test_security();
+ print_securities();
test_condition_test_virtualization();
test_condition_test_user();
test_condition_test_group();
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index de91efac72..2ec2dfc261 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Michael Marineau
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Michael Marineau
***/
#include <stdarg.h>
@@ -23,8 +8,10 @@
#include "alloc-util.h"
#include "conf-files.h"
+#include "fileio.h"
#include "fs-util.h"
#include "macro.h"
+#include "mkdir.h"
#include "parse-util.h"
#include "rm-rf.h"
#include "string-util.h"
@@ -35,12 +22,16 @@
static void setup_test_dir(char *tmp_dir, const char *files, ...) {
va_list ap;
- assert_se(mkdtemp(tmp_dir) != NULL);
+ assert_se(mkdtemp(tmp_dir));
va_start(ap, files);
- while (files != NULL) {
- _cleanup_free_ char *path = strappend(tmp_dir, files);
- assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID) == 0);
+ while (files) {
+ _cleanup_free_ char *path;
+
+ assert_se(path = strappend(tmp_dir, files));
+ (void) mkdir_parents(path, 0755);
+ assert_se(write_string_file(path, "foobar", WRITE_STRING_FILE_CREATE) >= 0);
+
files = va_arg(ap, const char *);
}
va_end(ap);
@@ -49,7 +40,7 @@ static void setup_test_dir(char *tmp_dir, const char *files, ...) {
static void test_conf_files_list(bool use_root) {
char tmp_dir[] = "/tmp/test-conf-files-XXXXXX";
_cleanup_strv_free_ char **found_files = NULL, **found_files2 = NULL;
- const char *root_dir, *search_1, *search_2, *expect_a, *expect_b, *expect_c;
+ const char *root_dir, *search_1, *search_2, *expect_a, *expect_b, *expect_c, *mask;
log_debug("/* %s */", __func__);
@@ -58,8 +49,12 @@ static void test_conf_files_list(bool use_root) {
"/dir2/a.conf",
"/dir2/b.conf",
"/dir2/c.foo",
+ "/dir2/d.conf",
NULL);
+ mask = strjoina(tmp_dir, "/dir1/d.conf");
+ assert_se(symlink("/dev/null", mask) >= 0);
+
if (use_root) {
root_dir = tmp_dir;
search_1 = "/dir1";
@@ -76,23 +71,23 @@ static void test_conf_files_list(bool use_root) {
log_debug("/* Check when filtered by suffix */");
- assert_se(conf_files_list(&found_files, ".conf", root_dir, 0, search_1, search_2, NULL) == 0);
+ assert_se(conf_files_list(&found_files, ".conf", root_dir, CONF_FILES_FILTER_MASKED, search_1, search_2, NULL) == 0);
strv_print(found_files);
assert_se(found_files);
assert_se(streq_ptr(found_files[0], expect_a));
assert_se(streq_ptr(found_files[1], expect_b));
- assert_se(found_files[2] == NULL);
+ assert_se(!found_files[2]);
log_debug("/* Check when unfiltered */");
- assert_se(conf_files_list(&found_files2, NULL, root_dir, 0, search_1, search_2, NULL) == 0);
+ assert_se(conf_files_list(&found_files2, NULL, root_dir, CONF_FILES_FILTER_MASKED, search_1, search_2, NULL) == 0);
strv_print(found_files2);
assert_se(found_files2);
assert_se(streq_ptr(found_files2[0], expect_a));
assert_se(streq_ptr(found_files2[1], expect_b));
assert_se(streq_ptr(found_files2[2], expect_c));
- assert_se(found_files2[3] == NULL);
+ assert_se(!found_files2[3]);
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index 028bf5ef3b..ff951d12f4 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -1,26 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "conf-parser.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
@@ -108,6 +91,7 @@ static void test_config_parse_path(void) {
test_config_parse_path_one("/path", "/path");
test_config_parse_path_one("/path//////////", "/path");
test_config_parse_path_one("///path/foo///bar////bar//", "/path/foo/bar/bar");
+ test_config_parse_path_one("/path//./////hogehoge///.", "/path/hogehoge");
test_config_parse_path_one("/path/\xc3\x80", "/path/\xc3\x80");
test_config_parse_path_one("not_absolute/path", NULL);
@@ -182,7 +166,7 @@ static void test_config_parse_strv(void) {
test_config_parse_strv_one("foo bar foo", STRV_MAKE("foo", "bar", "foo"));
test_config_parse_strv_one("\"foo bar\" foo", STRV_MAKE("foo bar", "foo"));
test_config_parse_strv_one("\xc3\x80", STRV_MAKE("\xc3\x80"));
- test_config_parse_strv_one("\xc3\x7f", STRV_MAKE_EMPTY);
+ test_config_parse_strv_one("\xc3\x7f", STRV_MAKE("\xc3\x7f"));
}
static void test_config_parse_mode(void) {
@@ -326,7 +310,7 @@ static const char* const config_file[] = {
};
static void test_config_parse(unsigned i, const char *s) {
- char name[] = "/tmp/test-conf-parser.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-conf-parser.XXXXXX";
int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *setting1 = NULL;
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index 1dde878a9e..2e8d251ac1 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
@@ -108,7 +90,7 @@ static void test_copy_tree(void) {
STRV_FOREACH(p, files) {
_cleanup_free_ char *f;
- assert_se((f = strappend(original_dir, *p)));
+ assert_se(f = strappend(original_dir, *p));
assert_se(mkdir_parents(f, 0755) >= 0);
assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0);
@@ -117,8 +99,8 @@ static void test_copy_tree(void) {
STRV_FOREACH_PAIR(link, p, links) {
_cleanup_free_ char *f, *l;
- assert_se((f = strappend(original_dir, *p)));
- assert_se((l = strappend(original_dir, *link)));
+ assert_se(f = strappend(original_dir, *p));
+ assert_se(l = strappend(original_dir, *link));
assert_se(mkdir_parents(l, 0755) >= 0);
assert_se(symlink(f, l) == 0);
@@ -130,10 +112,10 @@ static void test_copy_tree(void) {
assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE) == 0);
STRV_FOREACH(p, files) {
- _cleanup_free_ char *buf = NULL, *f;
- size_t sz = 0;
+ _cleanup_free_ char *buf, *f;
+ size_t sz;
- assert_se((f = strappend(copy_dir, *p)));
+ assert_se(f = strappend(copy_dir, *p));
assert_se(access(f, F_OK) == 0);
assert_se(read_full_file(f, &buf, &sz) == 0);
@@ -141,10 +123,10 @@ static void test_copy_tree(void) {
}
STRV_FOREACH_PAIR(link, p, links) {
- _cleanup_free_ char *target = NULL, *f, *l;
+ _cleanup_free_ char *target, *f, *l;
- assert_se((f = strjoin(original_dir, *p)));
- assert_se((l = strjoin(copy_dir, *link)));
+ assert_se(f = strjoin(original_dir, *p));
+ assert_se(l = strjoin(copy_dir, *link));
assert_se(chase_symlinks(l, NULL, 0, &target) == 1);
assert_se(path_equal(f, target));
@@ -253,7 +235,27 @@ static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint
unlink(fn3);
}
+static void test_copy_atomic(void) {
+ _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
+ const char *q;
+ int r;
+
+ assert_se(mkdtemp_malloc(NULL, &p) >= 0);
+
+ q = strjoina(p, "/fstab");
+
+ r = copy_file_atomic("/etc/fstab", q, 0644, 0, COPY_REFLINK);
+ if (r == -ENOENT)
+ return;
+
+ assert_se(copy_file_atomic("/etc/fstab", q, 0644, 0, COPY_REFLINK) == -EEXIST);
+
+ assert_se(copy_file_atomic("/etc/fstab", q, 0644, 0, COPY_REPLACE) >= 0);
+}
+
int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
+
test_copy_file();
test_copy_file_fd();
test_copy_tree();
@@ -264,6 +266,7 @@ int main(int argc, char *argv[]) {
test_copy_bytes_regular_file(argv[0], true, 1000);
test_copy_bytes_regular_file(argv[0], false, 32000); /* larger than copy buffer size */
test_copy_bytes_regular_file(argv[0], true, 32000);
+ test_copy_atomic();
return 0;
}
diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c
index 1a7220d17a..c9272459b4 100644
--- a/src/test/test-cpu-set-util.c
+++ b/src/test/test-cpu-set-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "cpu-set-util.h"
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
index 0e82ba634f..c8a83f0fc9 100644
--- a/src/test/test-daemon.c
+++ b/src/test/test-daemon.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
diff --git a/src/test/test-date.c b/src/test/test-date.c
index 85867db8dc..99b6f2eb9e 100644
--- a/src/test/test-date.c
+++ b/src/test/test-date.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c
index 042907c8e0..02496a121d 100644
--- a/src/test/test-device-nodes.c
+++ b/src/test/test-device-nodes.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Dave Reisner
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Dave Reisner
***/
#include <sys/types.h>
diff --git a/src/test/test-dissect-image.c b/src/test/test-dissect-image.c
index c594047c76..a0a909baf0 100644
--- a/src/test/test-dissect-image.c
+++ b/src/test/test-dissect-image.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stdio.h>
diff --git a/src/test/test-dlopen.c b/src/test/test-dlopen.c
index dd43da559f..148ebaa4d0 100644
--- a/src/test/test-dlopen.c
+++ b/src/test/test-dlopen.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dlfcn.h>
#include <stdlib.h>
@@ -26,7 +8,7 @@
int main(int argc, char **argv) {
void *handle;
- assert_se((handle = dlopen(argv[1], RTLD_NOW)));
+ assert_se(handle = dlopen(argv[1], RTLD_NOW));
assert_se(dlclose(handle) == 0);
return EXIT_SUCCESS;
diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c
index 0ad7d088aa..8ed7dbd1e6 100644
--- a/src/test/test-dns-domain.c
+++ b/src/test/test-dns-domain.c
@@ -1,21 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "alloc-util.h"
@@ -253,6 +237,7 @@ static void test_dns_name_between(void) {
test_dns_name_between_one("example", "example", "example", false);
test_dns_name_between_one("example", "example", "yljkjljk.a.example", false);
test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false);
+ test_dns_name_between_one("hkps.pool.sks-keyservers.net", "_pgpkey-https._tcp.hkps.pool.sks-keyservers.net", "ipv4.pool.sks-keyservers.net", true);
}
static void test_dns_name_endswith_one(const char *a, const char *b, int ret) {
diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c
index 421774c074..92692bd487 100644
--- a/src/test/test-ellipsize.c
+++ b/src/test/test-ellipsize.c
@@ -1,46 +1,127 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Shawn Landden
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
#include "alloc-util.h"
#include "def.h"
#include "string-util.h"
+#include "strv.h"
#include "terminal-util.h"
#include "util.h"
+#include "utf8.h"
+
+static void test_ellipsize_mem_one(const char *s, size_t old_length, size_t new_length) {
+ _cleanup_free_ char *n = NULL;
+ _cleanup_free_ char *t1 = NULL, *t2 = NULL, *t3 = NULL;
+ char buf[LINE_MAX];
+ bool has_wide_chars;
+ size_t max_width;
+
+ n = memdup_suffix0(s, old_length);
+
+ if (!utf8_is_valid(n))
+ /* We don't support invalid sequences… */
+ return;
+
+ /* Report out inputs. We duplicate the data so that cellescape
+ * can properly report truncated multibyte sequences. */
+ log_info("%s \"%s\" old_length=%zu/%zu new_length=%zu", __func__,
+ cellescape(buf, sizeof buf, n),
+ old_length, utf8_console_width(n),
+ new_length);
+
+ /* To keep this test simple, any case with wide chars starts with this glyph */
+ has_wide_chars = startswith(s, "你");
+ max_width = MIN(utf8_console_width(n), new_length);
+
+ t1 = ellipsize_mem(n, old_length, new_length, 30);
+ log_info("30%% → %s utf8_console_width=%zu", t1, utf8_console_width(t1));
+ if (!has_wide_chars)
+ assert_se(utf8_console_width(t1) == max_width);
+ else
+ assert_se(utf8_console_width(t1) <= max_width);
+
+ t2 = ellipsize_mem(n, old_length, new_length, 90);
+ log_info("90%% → %s utf8_console_width=%zu", t2, utf8_console_width(t2));
+ if (!has_wide_chars)
+ assert_se(utf8_console_width(t2) == max_width);
+ else
+ assert_se(utf8_console_width(t2) <= max_width);
+
+ t3 = ellipsize_mem(n, old_length, new_length, 100);
+ log_info("100%% → %s utf8_console_width=%zu", t3, utf8_console_width(t3));
+ if (!has_wide_chars)
+ assert_se(utf8_console_width(t3) == max_width);
+ else
+ assert_se(utf8_console_width(t3) <= max_width);
+
+ if (new_length >= old_length) {
+ assert_se(streq(t1, n));
+ assert_se(streq(t2, n));
+ assert_se(streq(t3, n));
+ }
+}
-static void test_one(const char *p) {
+static void test_ellipsize_mem(void) {
+ const char *s;
+ ssize_t l, k;
+
+ FOREACH_STRING(s,
+ "_XXXXXXXXXXX_", /* ASCII */
+ "_aąęółśćńżźć_", /* two-byte utf-8 */
+ "გამარჯობა", /* multi-byte utf-8 */
+ "你好世界", /* wide characters */
+ "你გą世óoó界") /* a mix */
+
+ for (l = strlen(s); l >= 0; l--)
+ for (k = strlen(s) + 1; k >= 0; k--)
+ test_ellipsize_mem_one(s, l, k);
+}
+
+static void test_ellipsize_one(const char *p) {
_cleanup_free_ char *t;
t = ellipsize(p, columns(), 70);
puts(t);
+ free(t);
+ t = ellipsize(p, columns(), 0);
+ puts(t);
+ free(t);
+ t = ellipsize(p, columns(), 100);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 0, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 1, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 2, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 3, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 4, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 5, 50);
+ puts(t);
+}
+
+static void test_ellipsize(void) {
+ test_ellipsize_one(DIGITS LETTERS DIGITS LETTERS);
+ test_ellipsize_one("한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어");
+ test_ellipsize_one("-日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国");
+ test_ellipsize_one("中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国-中国中国中国中国中国中国中国中国中国中国中国中国中国");
+ test_ellipsize_one("sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd");
+ test_ellipsize_one("🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮");
+ test_ellipsize_one("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
+ test_ellipsize_one("shórt");
}
int main(int argc, char *argv[]) {
- test_one(DIGITS LETTERS DIGITS LETTERS);
- test_one("한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어");
- test_one("-日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国");
- test_one("中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国-中国中国中国中国中国中国中国中国中国中国中国中国中国");
- test_one("sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd");
- test_one("🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮");
- test_one("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
- test_one("shórt");
+ test_ellipsize_mem();
+ test_ellipsize();
return 0;
}
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
index a7cdbb6018..d072a15cb1 100644
--- a/src/test/test-engine.c
+++ b/src/test/test-engine.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
@@ -31,13 +13,15 @@
int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
- Manager *m = NULL;
- Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL;
- FILE *serial = NULL;
- FDSet *fdset = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
+ Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL, *unit_with_multiple_dashes = NULL;
Job *j;
int r;
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
r = enter_cgroup_subroot();
if (r == -ENOMEDIUM) {
log_notice_errno(r, "Skipping test: cgroupfs not available");
@@ -47,18 +31,18 @@ int main(int argc, char *argv[]) {
/* prepare the test */
assert_se(set_unit_path(get_testdata_dir("")) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
- r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
+ r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m);
if (MANAGER_SKIP_TEST(r)) {
log_notice_errno(r, "Skipping test: manager_new: %m");
return EXIT_TEST_SKIP;
}
assert_se(r >= 0);
- assert_se(manager_startup(m, serial, fdset) >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
printf("Load1:\n");
- assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0);
- assert_se(manager_load_unit(m, "b.service", NULL, NULL, &b) >= 0);
- assert_se(manager_load_unit(m, "c.service", NULL, NULL, &c) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "a.service", NULL, &a) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "b.service", NULL, &b) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "c.service", NULL, &c) >= 0);
manager_dump_units(m, stdout, "\t");
printf("Test1: (Trivial)\n");
@@ -70,8 +54,8 @@ int main(int argc, char *argv[]) {
printf("Load2:\n");
manager_clear_jobs(m);
- assert_se(manager_load_unit(m, "d.service", NULL, NULL, &d) >= 0);
- assert_se(manager_load_unit(m, "e.service", NULL, NULL, &e) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "d.service", NULL, &d) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "e.service", NULL, &e) >= 0);
manager_dump_units(m, stdout, "\t");
printf("Test2: (Cyclic Order, Unfixable)\n");
@@ -87,7 +71,7 @@ int main(int argc, char *argv[]) {
manager_dump_jobs(m, stdout, "\t");
printf("Load3:\n");
- assert_se(manager_load_unit(m, "g.service", NULL, NULL, &g) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "g.service", NULL, &g) >= 0);
manager_dump_units(m, stdout, "\t");
printf("Test5: (Colliding transaction, fail)\n");
@@ -109,7 +93,7 @@ int main(int argc, char *argv[]) {
manager_dump_jobs(m, stdout, "\t");
printf("Load4:\n");
- assert_se(manager_load_unit(m, "h.service", NULL, NULL, &h) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "h.service", NULL, &h) >= 0);
manager_dump_units(m, stdout, "\t");
printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
@@ -143,7 +127,10 @@ int main(int argc, char *argv[]) {
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c));
assert_se(!hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
- manager_free(m);
+ assert_se(manager_load_unit(m, "unit-with-multiple-dashes.service", NULL, NULL, &unit_with_multiple_dashes) >= 0);
+
+ assert_se(strv_equal(unit_with_multiple_dashes->documentation, STRV_MAKE("man:test", "man:override2", "man:override3")));
+ assert_se(streq_ptr(unit_with_multiple_dashes->description, "override4"));
return 0;
}
diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c
index b1e69d4a5a..e645d4968e 100644
--- a/src/test/test-env-util.c
+++ b/src/test/test-env-util.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
@@ -277,8 +258,9 @@ static void test_env_clean(void) {
assert_se(streq(e[1], "X="));
assert_se(streq(e[2], "F=F"));
assert_se(streq(e[3], "abcd=äöüß"));
- assert_se(streq(e[4], "another=final one"));
- assert_se(e[5] == NULL);
+ assert_se(streq(e[4], "xyz=xyz\n"));
+ assert_se(streq(e[5], "another=final one"));
+ assert_se(e[6] == NULL);
}
static void test_env_name_is_valid(void) {
@@ -297,6 +279,8 @@ static void test_env_value_is_valid(void) {
assert_se(env_value_is_valid(""));
assert_se(env_value_is_valid("głąb kapuściany"));
assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
+ assert_se(env_value_is_valid("tab\tcharacter"));
+ assert_se(env_value_is_valid("new\nline"));
}
static void test_env_assignment_is_valid(void) {
@@ -304,6 +288,8 @@ static void test_env_assignment_is_valid(void) {
assert_se(env_assignment_is_valid("b=głąb kapuściany"));
assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
+ assert_se(env_assignment_is_valid("f=tab\tcharacter"));
+ assert_se(env_assignment_is_valid("g=new\nline"));
assert_se(!env_assignment_is_valid("="));
assert_se(!env_assignment_is_valid("a b="));
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
index aa05520abd..650a9a058d 100644
--- a/src/test/test-escape.c
+++ b/src/test/test-escape.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "escape.h"
diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c
index bd9c809296..cfc8b5f88e 100644
--- a/src/test/test-exec-util.c
+++ b/src/test/test-exec-util.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -249,7 +230,6 @@ const gather_stdout_callback_t gather_stdout[] = {
gather_stdout_three,
};
-
static void test_stdout_gathering(void) {
char template[] = "/tmp/test-exec-util.XXXXXXX";
const char *dirs[] = {template, NULL};
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 645e0b3d47..fa8efdddd2 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <grp.h>
#include <pwd.h>
@@ -37,6 +19,7 @@
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
+#include "service.h"
#include "stat-util.h"
#include "test-helper.h"
#include "tests.h"
@@ -145,7 +128,7 @@ static void test(Manager *m, const char *unit_name, int status_expected, int cod
assert_se(unit_name);
- assert_se(manager_load_unit(m, unit_name, NULL, NULL, &unit) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
check(m, unit, status_expected, code_expected);
}
@@ -188,6 +171,7 @@ static void test_exec_workingdirectory(Manager *m) {
assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0);
test(m, "exec-workingdirectory.service", 0, CLD_EXITED);
+ test(m, "exec-workingdirectory-trailing-dot.service", 0, CLD_EXITED);
(void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
}
@@ -244,6 +228,7 @@ static void test_exec_privatedevices(Manager *m) {
test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED);
test(m, "exec-privatedevices-no.service", 0, CLD_EXITED);
+ test(m, "exec-privatedevices-disabled-by-prefix.service", 0, CLD_EXITED);
/* We use capsh to test if the capabilities are
* properly set, so be sure that it exists */
@@ -370,6 +355,9 @@ static void test_exec_restrictnamespaces(Manager *m) {
test(m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
test(m, "exec-restrictnamespaces-mnt.service", 0, CLD_EXITED);
test(m, "exec-restrictnamespaces-mnt-blacklist.service", 1, CLD_EXITED);
+ test(m, "exec-restrictnamespaces-merge-and.service", 0, CLD_EXITED);
+ test(m, "exec-restrictnamespaces-merge-or.service", 0, CLD_EXITED);
+ test(m, "exec-restrictnamespaces-merge-all.service", 0, CLD_EXITED);
#endif
}
@@ -443,8 +431,14 @@ static void test_exec_dynamicuser(Manager *m) {
test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED);
test(m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED);
+ (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
+
test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
test(m, "exec-dynamicuser-statedir-migrate-step2.service", 0, CLD_EXITED);
+
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
@@ -466,7 +460,9 @@ static void test_exec_environmentfile(Manager *m) {
"; comment2\n"
" ; # comment3\n"
"line without an equal\n"
- "VAR3='$word 5 6'\n";
+ "VAR3='$word 5 6'\n"
+ "VAR4='new\nline'\n"
+ "VAR5=password\\with\\backslashes";
int r;
r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
@@ -492,12 +488,16 @@ static void test_exec_passenvironment(Manager *m) {
assert_se(setenv("VAR1", "word1 word2", 1) == 0);
assert_se(setenv("VAR2", "word3", 1) == 0);
assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
+ assert_se(setenv("VAR4", "new\nline", 1) == 0);
+ assert_se(setenv("VAR5", "passwordwithbackslashes", 1) == 0);
test(m, "exec-passenvironment.service", 0, CLD_EXITED);
test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
assert_se(unsetenv("VAR1") == 0);
assert_se(unsetenv("VAR2") == 0);
assert_se(unsetenv("VAR3") == 0);
+ assert_se(unsetenv("VAR4") == 0);
+ assert_se(unsetenv("VAR5") == 0);
test(m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
}
@@ -546,6 +546,10 @@ static void test_exec_capabilityboundingset(Manager *m) {
test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
}
+static void test_exec_basic(Manager *m) {
+ test(m, "exec-basic.service", 0, CLD_EXITED);
+}
+
static void test_exec_ambientcapabilities(Manager *m) {
int r;
@@ -623,12 +627,12 @@ static void test_exec_standardinput(Manager *m) {
static int run_tests(UnitFileScope scope, const test_function_t *tests) {
const test_function_t *test = NULL;
- Manager *m = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
int r;
assert_se(tests);
- r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m);
+ r = manager_new(scope, MANAGER_TEST_RUN_BASIC, &m);
if (MANAGER_SKIP_TEST(r)) {
log_notice_errno(r, "Skipping test: manager_new: %m");
return EXIT_TEST_SKIP;
@@ -639,14 +643,13 @@ static int run_tests(UnitFileScope scope, const test_function_t *tests) {
for (test = tests; test && *test; test++)
(*test)(m);
- manager_free(m);
-
return 0;
}
int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
static const test_function_t user_tests[] = {
+ test_exec_basic,
test_exec_ambientcapabilities,
test_exec_bindpaths,
test_exec_capabilityboundingset,
@@ -693,6 +696,7 @@ int main(int argc, char *argv[]) {
(void) unsetenv("USER");
(void) unsetenv("LOGNAME");
+ (void) unsetenv("SHELL");
/* It is needed otherwise cgroup creation fails */
if (getuid() != 0) {
diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c
index 3e7c197cfe..30019382ae 100644
--- a/src/test/test-extract-word.c
+++ b/src/test/test-extract-word.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
index 3f94df2eee..a04403d748 100644
--- a/src/test/test-fd-util.c
+++ b/src/test/test-fd-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <unistd.h>
@@ -71,9 +53,9 @@ static void test_same_fd(void) {
_cleanup_close_ int a = -1, b = -1, c = -1;
assert_se(pipe2(p, O_CLOEXEC) >= 0);
- assert_se((a = dup(p[0])) >= 0);
+ assert_se((a = fcntl(p[0], F_DUPFD, 3)) >= 0);
assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
- assert_se((c = dup(a)) >= 0);
+ assert_se((c = fcntl(a, F_DUPFD, 3)) >= 0);
assert_se(same_fd(p[0], p[0]) > 0);
assert_se(same_fd(p[1], p[1]) > 0);
@@ -241,7 +223,101 @@ static void test_rearrange_stdio(void) {
}
}
+static void assert_equal_fd(int fd1, int fd2) {
+
+ for (;;) {
+ uint8_t a[4096], b[4096];
+ ssize_t x, y;
+
+ x = read(fd1, a, sizeof(a));
+ assert(x >= 0);
+
+ y = read(fd2, b, sizeof(b));
+ assert(y >= 0);
+
+ assert(x == y);
+
+ if (x == 0)
+ break;
+
+ assert(memcmp(a, b, x) == 0);
+ }
+}
+
+static void test_fd_duplicate_data_fd(void) {
+ _cleanup_close_ int fd1 = -1, fd2 = -1;
+ _cleanup_(close_pairp) int sfd[2] = { -1, -1 };
+ _cleanup_(sigkill_waitp) pid_t pid = -1;
+ uint64_t i, j;
+ int r;
+
+ fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
+ if (fd1 >= 0) {
+
+ fd2 = fd_duplicate_data_fd(fd1);
+ assert_se(fd2 >= 0);
+
+ assert_se(lseek(fd1, 0, SEEK_SET) == 0);
+ assert_equal_fd(fd1, fd2);
+ }
+
+ fd1 = safe_close(fd1);
+ fd2 = safe_close(fd2);
+
+ fd1 = acquire_data_fd("hallo", 6, 0);
+ assert_se(fd1 >= 0);
+
+ fd2 = fd_duplicate_data_fd(fd1);
+ assert_se(fd2 >= 0);
+
+ safe_close(fd1);
+ fd1 = acquire_data_fd("hallo", 6, 0);
+ assert_se(fd1 >= 0);
+
+ assert_equal_fd(fd1, fd2);
+
+ fd1 = safe_close(fd1);
+ fd2 = safe_close(fd2);
+
+ assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
+
+ r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ /* child */
+
+ sfd[0] = safe_close(sfd[0]);
+
+ for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++)
+ assert_se(write(sfd[1], &i, sizeof(i)) == sizeof(i));
+
+ sfd[1] = safe_close(sfd[1]);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ sfd[1] = safe_close(sfd[1]);
+
+ fd2 = fd_duplicate_data_fd(sfd[0]);
+ assert_se(fd2 >= 0);
+
+ for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++) {
+ assert_se(read(fd2, &j, sizeof(j)) == sizeof(j));
+ assert_se(i == j);
+ }
+
+ assert_se(read(fd2, &j, sizeof(j)) == 0);
+}
+
+static void test_read_nr_open(void) {
+ log_info("nr-open: %i", read_nr_open());
+}
+
int main(int argc, char *argv[]) {
+
+ log_set_max_level(LOG_DEBUG);
+
test_close_many();
test_close_nointr();
test_same_fd();
@@ -249,6 +325,8 @@ int main(int argc, char *argv[]) {
test_acquire_data_fd();
test_fd_move_above_stdio();
test_rearrange_stdio();
+ test_fd_duplicate_data_fd();
+ test_read_nr_open();
return 0;
}
diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c
index bc5d5d4f2b..7d68a6b966 100644
--- a/src/test/test-fdset.c
+++ b/src/test/test-fdset.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <unistd.h>
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index c6128c9091..14ba075144 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stdio.h>
@@ -28,6 +10,7 @@
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "io-util.h"
#include "parse-util.h"
#include "process-util.h"
@@ -36,7 +19,8 @@
#include "util.h"
static void test_parse_env_file(void) {
- char t[] = "/tmp/test-fileio-in-XXXXXX",
+ _cleanup_(unlink_tempfilep) char
+ t[] = "/tmp/test-fileio-in-XXXXXX",
p[] = "/tmp/test-fileio-out-XXXXXX";
int fd, r;
FILE *f;
@@ -106,7 +90,7 @@ static void test_parse_env_file(void) {
}
r = parse_env_file(
- t, NULL,
+ NULL, t, NULL,
"one", &one,
"two", &two,
"three", &three,
@@ -148,13 +132,11 @@ static void test_parse_env_file(void) {
r = load_env_file(NULL, p, NULL, &b);
assert_se(r >= 0);
-
- unlink(t);
- unlink(p);
}
static void test_parse_multiline_env_file(void) {
- char t[] = "/tmp/test-fileio-in-XXXXXX",
+ _cleanup_(unlink_tempfilep) char
+ t[] = "/tmp/test-fileio-in-XXXXXX",
p[] = "/tmp/test-fileio-out-XXXXXX";
int fd, r;
FILE *f;
@@ -202,13 +184,10 @@ static void test_parse_multiline_env_file(void) {
r = load_env_file(NULL, p, NULL, &b);
assert_se(r >= 0);
-
- unlink(t);
- unlink(p);
}
static void test_merge_env_file(void) {
- char t[] = "/tmp/test-fileio-XXXXXX";
+ _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **a = NULL;
@@ -277,7 +256,7 @@ static void test_merge_env_file(void) {
}
static void test_merge_env_file_invalid(void) {
- char t[] = "/tmp/test-fileio-XXXXXX";
+ _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **a = NULL;
@@ -316,9 +295,9 @@ static void test_merge_env_file_invalid(void) {
}
static void test_executable_is_script(void) {
- char t[] = "/tmp/test-executable-XXXXXX";
+ _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
int fd, r;
- FILE *f;
+ _cleanup_fclose_ FILE *f = NULL;
char *command;
fd = mkostemp_safe(t);
@@ -344,9 +323,6 @@ static void test_executable_is_script(void) {
assert_se(startswith(command, "/"));
free(command);
}
-
- fclose(f);
- unlink(t);
}
static void test_status_field(void) {
@@ -405,8 +381,8 @@ static void test_capeff(void) {
}
static void test_write_string_stream(void) {
- char fn[] = "/tmp/test-write_string_stream-XXXXXX";
- FILE *f = NULL;
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_stream-XXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
int fd;
char buf[64];
@@ -437,13 +413,10 @@ static void test_write_string_stream(void) {
assert_se(fgets(buf, sizeof(buf), f));
printf(">%s<", buf);
assert_se(streq(buf, "boohoo"));
- f = safe_fclose(f);
-
- unlink(fn);
}
static void test_write_string_file(void) {
- char fn[] = "/tmp/test-write_string_file-XXXXXX";
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file-XXXXXX";
char buf[64] = {};
_cleanup_close_ int fd;
@@ -454,12 +427,10 @@ static void test_write_string_file(void) {
assert_se(read(fd, buf, sizeof(buf)) == 7);
assert_se(streq(buf, "boohoo\n"));
-
- unlink(fn);
}
static void test_write_string_file_no_create(void) {
- char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
_cleanup_close_ int fd;
char buf[64] = {0};
@@ -471,8 +442,6 @@ static void test_write_string_file_no_create(void) {
assert_se(read(fd, buf, sizeof(buf)) == STRLEN("boohoo\n"));
assert_se(streq(buf, "boohoo\n"));
-
- unlink(fn);
}
static void test_write_string_file_verify(void) {
@@ -480,7 +449,7 @@ static void test_write_string_file_verify(void) {
int r;
assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0);
- assert_se((buf2 = strjoin(buf, "\n")));
+ assert_se(buf2 = strjoin(buf, "\n"));
r = write_string_file("/proc/cmdline", buf, 0);
assert_se(IN_SET(r, -EACCES, -EIO));
@@ -496,9 +465,8 @@ static void test_write_string_file_verify(void) {
}
static void test_load_env_file_pairs(void) {
- char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
- int fd;
- int r;
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
+ int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **l = NULL;
char **k, **v;
@@ -535,15 +503,13 @@ static void test_load_env_file_pairs(void) {
if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
}
-
- unlink(fn);
}
static void test_search_and_fopen(void) {
const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
+
char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
+ int fd, r;
FILE *f;
fd = mkostemp_safe(name);
@@ -574,12 +540,11 @@ static void test_search_and_fopen(void) {
assert_se(r < 0);
}
-
static void test_search_and_fopen_nulstr(void) {
const char dirs[] = "/tmp/foo/bar\0/tmp\0";
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
+
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd, r;
FILE *f;
fd = mkostemp_safe(name);
@@ -607,12 +572,12 @@ static void test_search_and_fopen_nulstr(void) {
}
static void test_writing_tmpfile(void) {
- char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
_cleanup_free_ char *contents = NULL;
size_t size;
- int r;
_cleanup_close_ int fd = -1;
struct iovec iov[3];
+ int r;
iov[0] = IOVEC_MAKE_STRING("abc\n");
iov[1] = IOVEC_MAKE_STRING(ALPHANUMERICAL "\n");
@@ -628,8 +593,6 @@ static void test_writing_tmpfile(void) {
assert_se(r == 0);
printf("contents: %s", contents);
assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
-
- unlink(name);
}
static void test_tempfn(void) {
@@ -717,7 +680,7 @@ static void test_read_line(void) {
}
static void test_read_line2(void) {
- char name[] = "/tmp/test-fileio.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fileio.XXXXXX";
int fd;
_cleanup_fclose_ FILE *f = NULL;
diff --git a/src/test/test-firewall-util.c b/src/test/test-firewall-util.c
index 38e433a762..1b62590b49 100644
--- a/src/test/test-firewall-util.c
+++ b/src/test/test-firewall-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "firewall-util.h"
#include "log.h"
diff --git a/src/test/test-format-table.c b/src/test/test-format-table.c
new file mode 100644
index 0000000000..adcc414161
--- /dev/null
+++ b/src/test/test-format-table.c
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "format-table.h"
+#include "string-util.h"
+#include "time-util.h"
+
+int main(int argc, char *argv[]) {
+
+ _cleanup_(table_unrefp) Table *t = NULL;
+ _cleanup_free_ char *formatted = NULL;
+
+ assert_se(setenv("COLUMNS", "40", 1) >= 0);
+
+ assert_se(t = table_new("ONE", "TWO", "THREE"));
+
+ assert_se(table_set_align_percent(t, TABLE_HEADER_CELL(2), 100) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "xxx",
+ TABLE_STRING, "yyy",
+ TABLE_BOOLEAN, true) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "a long field",
+ TABLE_STRING, "yyy",
+ TABLE_BOOLEAN, false) >= 0);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "ONE TWO THREE\n"
+ "xxx yyy yes\n"
+ "a long field yyy no\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, 40);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "ONE TWO THREE\n"
+ "xxx yyy yes\n"
+ "a long field yyy no\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, 12);
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "ONE TWO THR…\n"
+ "xxx yyy yes\n"
+ "a … yyy no\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, 5);
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "… … …\n"
+ "… … …\n"
+ "… … …\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, 3);
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "… … …\n"
+ "… … …\n"
+ "… … …\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, (size_t) -1);
+ assert_se(table_set_sort(t, (size_t) 0, (size_t) 2, (size_t) -1) >= 0);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "ONE TWO THREE\n"
+ "a long field yyy no\n"
+ "xxx yyy yes\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_header(t, false);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "fäää",
+ TABLE_STRING, "uuu",
+ TABLE_BOOLEAN, true) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "fäää",
+ TABLE_STRING, "zzz",
+ TABLE_BOOLEAN, false) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_EMPTY,
+ TABLE_SIZE, (uint64_t) 4711,
+ TABLE_TIMESPAN, (usec_t) 5*USEC_PER_MINUTE) >= 0);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "a long field yyy no\n"
+ "fäää zzz no\n"
+ "fäää uuu yes\n"
+ "xxx yyy yes\n"
+ " 4.6K 5min\n"));
+
+ formatted = mfree(formatted);
+
+ assert_se(table_set_display(t, (size_t) 2, (size_t) 0, (size_t) 2, (size_t) 0, (size_t) 0, (size_t) -1) >= 0);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ " no a long f… no a long f… a long fi…\n"
+ " no fäää no fäää fäää \n"
+ " yes fäää yes fäää fäää \n"
+ " yes xxx yes xxx xxx \n"
+ "5min 5min \n"));
+
+ return 0;
+}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index ebcec4fcc5..fc650b513e 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
@@ -270,17 +252,13 @@ static void test_chase_symlinks(void) {
pfd = chase_symlinks(p, NULL, CHASE_OPEN, NULL);
if (pfd != -ENOENT) {
- char procfs[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(pfd) + 1];
_cleanup_close_ int fd = -1;
sd_id128_t a, b;
assert_se(pfd >= 0);
- xsprintf(procfs, "/proc/self/fd/%i", pfd);
-
- fd = open(procfs, O_RDONLY|O_CLOEXEC);
+ fd = fd_reopen(pfd, O_RDONLY|O_CLOEXEC);
assert_se(fd >= 0);
-
safe_close(pfd);
assert_se(id128_read_fd(fd, ID128_PLAIN, &a) >= 0);
@@ -288,6 +266,49 @@ static void test_chase_symlinks(void) {
assert_se(sd_id128_equal(a, b));
}
+ /* Test CHASE_ONE */
+
+ p = strjoina(temp, "/start");
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/top/dot/dotdota");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/top/./dotdota");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/top/../a");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/a");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/b");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ assert_se(streq("/usr", result));
+ result = mfree(result);
+
+ r = chase_symlinks("/usr", NULL, CHASE_STEP, &result);
+ assert_se(r > 0);
+ assert_se(streq("/usr", result));
+ result = mfree(result);
+
assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
@@ -317,7 +338,7 @@ static void test_readlink_and_make_absolute(void) {
char *r = NULL;
_cleanup_free_ char *pwd = NULL;
- assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), false) >= 0);
+ assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), MKDIR_WARN_MODE) >= 0);
assert_se(touch(name) >= 0);
assert_se(symlink(name, name_alias) >= 0);
diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c
index 081ec6a901..bd873a39be 100644
--- a/src/test/test-fstab-util.c
+++ b/src/test/test-fstab-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 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 "alloc-util.h"
#include "fstab-util.h"
diff --git a/src/test/test-gcrypt-util.c b/src/test/test-gcrypt-util.c
index d7d13a1303..b28b4eb5a2 100644
--- a/src/test/test-gcrypt-util.c
+++ b/src/test/test-gcrypt-util.c
@@ -1,6 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+
- * Copyright 2018 Zbigniew Jędrzejewski-Szmek
- */
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
#include "gcrypt-util.h"
diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c
index a30e04016f..d78d6223c0 100644
--- a/src/test/test-glob-util.c
+++ b/src/test/test-glob-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <glob.h>
diff --git a/src/test/test-hash.c b/src/test/test-hash.c
index d84a6a8859..f5bc131846 100644
--- a/src/test/test-hash.c
+++ b/src/test/test-hash.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index 1725766e5a..b695d4ee35 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd
-
- Copyright 2013 Daniel Buch
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Daniel Buch
***/
#include "alloc-util.h"
diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c
index ad0b7390e9..b319fa6ba9 100644
--- a/src/test/test-hashmap.c
+++ b/src/test/test-hashmap.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd
-
- Copyright 2013 Daniel Buch
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Daniel Buch
***/
#include "hashmap.h"
@@ -138,7 +123,7 @@ static void test_iterated_cache(void) {
}
static void test_path_hashmap(void) {
- _cleanup_(hashmap_freep) Hashmap *h = NULL;
+ _cleanup_hashmap_free_ Hashmap *h = NULL;
assert_se(h = hashmap_new(&path_hash_ops));
diff --git a/src/test/test-helper.c b/src/test/test-helper.c
index c371e199ba..9cf9972380 100644
--- a/src/test/test-helper.c
+++ b/src/test/test-helper.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "test-helper.h"
#include "random-util.h"
diff --git a/src/test/test-helper.h b/src/test/test-helper.h
index 1ee93f5c55..3e8ccd9049 100644
--- a/src/test/test-helper.h
+++ b/src/test/test-helper.h
@@ -2,22 +2,7 @@
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Holger Hans Peter Freyther
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Holger Hans Peter Freyther
***/
#include "sd-daemon.h"
diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c
index 3e25a0bac8..da9f3008bb 100644
--- a/src/test/test-hexdecoct.c
+++ b/src/test/test-hexdecoct.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
@@ -89,20 +71,40 @@ static void test_undecchar(void) {
assert_se(undecchar('9') == 9);
}
-static void test_unhexmem(void) {
- const char *hex = "efa2149213";
- const char *hex_invalid = "efa214921o";
- _cleanup_free_ char *hex2 = NULL;
+static void test_unhexmem_one(const char *s, size_t l, int retval) {
+ _cleanup_free_ char *hex = NULL;
_cleanup_free_ void *mem = NULL;
size_t len;
- assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(s, l, &mem, &len) == retval);
+ if (retval == 0) {
+ char *answer;
+
+ if (l == (size_t) -1)
+ l = strlen(s);
+
+ assert_se(hex = hexmem(mem, len));
+ answer = strndupa(s, l);
+ assert_se(streq(delete_chars(answer, WHITESPACE), hex));
+ }
+}
+
+static void test_unhexmem(void) {
+ const char *hex = "efa2149213";
+ const char *hex_space = " e f a\n 2\r 14\n\r\t9\t2 \n1\r3 \r\r\t";
+ const char *hex_invalid = "efa214921o";
- assert_se((hex2 = hexmem(mem, len)));
- assert_se(streq(hex, hex2));
+ test_unhexmem_one(NULL, 0, 0);
+ test_unhexmem_one("", 0, 0);
+ test_unhexmem_one("", (size_t) -1, 0);
+ test_unhexmem_one(" \n \t\r \t\t \n\n\n", (size_t) -1, 0);
+ test_unhexmem_one(hex_invalid, strlen(hex_invalid), -EINVAL);
+ test_unhexmem_one(hex_invalid, (size_t) - 1, -EINVAL);
+ test_unhexmem_one(hex, strlen(hex) - 1, -EPIPE);
+ test_unhexmem_one(hex, strlen(hex), 0);
+ test_unhexmem_one(hex, (size_t) -1, 0);
+ test_unhexmem_one(hex_space, strlen(hex_space), 0);
+ test_unhexmem_one(hex_space, (size_t) -1, 0);
}
/* https://tools.ietf.org/html/rfc4648#section-10 */
@@ -180,94 +182,65 @@ static void test_base32hexmem(void) {
free(b32);
}
-static void test_unbase32hexmem(void) {
- void *mem;
+static void test_unbase32hexmem_one(const char *hex, bool padding, int retval, const char *ans) {
+ _cleanup_free_ void *mem = NULL;
size_t len;
- assert_se(unbase32hexmem("", STRLEN(""), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO======", STRLEN("CO======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG====", STRLEN("CPNG===="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU===", STRLEN("CPNMU==="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", STRLEN("CPNMUOG="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8======", STRLEN("CPNMUOJ1E8======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("A", STRLEN("A"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A=======", STRLEN("A======="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA=====", STRLEN("AAA====="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA==", STRLEN("AAAAAA=="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB======", STRLEN("AB======"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB====", STRLEN("AAAB===="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB===", STRLEN("AAAAB==="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB=", STRLEN("AAAAAAB="), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("XPNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CXNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPXMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNXUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMXOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUXJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOX1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJX", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("", STRLEN(""), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO", STRLEN("CO"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG", STRLEN("CPNG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU", STRLEN("CPNMU"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG", STRLEN("CPNMUOG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", STRLEN("CPNMUOJ1"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8", STRLEN("CPNMUOJ1E8"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", STRLEN("CPNMUOG="), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJ1E8======", STRLEN("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", STRLEN("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", STRLEN("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA", STRLEN("AAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA", STRLEN("AAAAAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB", STRLEN("AB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB", STRLEN("AAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB", STRLEN("AAAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB", STRLEN("AAAAAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem(hex, (size_t) -1, padding, &mem, &len) == retval);
+ if (retval == 0) {
+ char *str;
+
+ str = strndupa(mem, len);
+ assert_se(streq(str, ans));
+ }
+}
+
+static void test_unbase32hexmem(void) {
+ test_unbase32hexmem_one("", true, 0, "");
+
+ test_unbase32hexmem_one("CO======", true, 0, "f");
+ test_unbase32hexmem_one("CPNG====", true, 0, "fo");
+ test_unbase32hexmem_one("CPNMU===", true, 0, "foo");
+ test_unbase32hexmem_one("CPNMUOG=", true, 0, "foob");
+ test_unbase32hexmem_one("CPNMUOJ1", true, 0, "fooba");
+ test_unbase32hexmem_one("CPNMUOJ1E8======", true, 0, "foobar");
+
+ test_unbase32hexmem_one("A", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("A=======", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAA=====", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAA==", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AB======", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAB====", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAB===", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAAB=", true, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("XPNMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CXNMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPXMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNXUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMXOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUXJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOX1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOJX", true, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("", false, 0, "");
+ test_unbase32hexmem_one("CO", false, 0, "f");
+ test_unbase32hexmem_one("CPNG", false, 0, "fo");
+ test_unbase32hexmem_one("CPNMU", false, 0, "foo");
+ test_unbase32hexmem_one("CPNMUOG", false, 0, "foob");
+ test_unbase32hexmem_one("CPNMUOJ1", false, 0, "fooba");
+ test_unbase32hexmem_one("CPNMUOJ1E8", false, 0, "foobar");
+ test_unbase32hexmem_one("CPNMUOG=", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOJ1E8======", false, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("A", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("A", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAA", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAA", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAAB", false, -EINVAL, NULL);
}
/* https://tools.ietf.org/html/rfc4648#section-10 */
diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c
index 329354831b..194a640eee 100644
--- a/src/test/test-hostname-util.c
+++ b/src/test/test-hostname-util.c
@@ -1,24 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
- Copyright 2015 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 "alloc-util.h"
#include "fileio.h"
diff --git a/src/test/test-hostname.c b/src/test/test-hostname.c
index febb4c64c7..710c0572e6 100644
--- a/src/test/test-hostname.c
+++ b/src/test/test-hostname.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "hostname-setup.h"
#include "util.h"
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index dba7283769..e3d07a69f3 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
diff --git a/src/test/test-in-addr-util.c b/src/test/test-in-addr-util.c
index 73692ec411..5b6e87bf5a 100644
--- a/src/test/test-in-addr-util.c
+++ b/src/test/test-in-addr-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/in.h>
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
index efdd82a797..15dd3c6966 100644
--- a/src/test/test-install-root.c
+++ b/src/test/test-install-root.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "fileio.h"
@@ -30,7 +12,7 @@ static void test_basic_mask_and_enable(const char *root) {
const char *p;
UnitFileState state;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
log_set_max_level(LOG_DEBUG);
@@ -171,7 +153,7 @@ static void test_linked_units(const char *root) {
const char *p, *q;
UnitFileState state;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0, i;
+ size_t n_changes = 0, i;
/*
* We'll test three cases here:
@@ -316,7 +298,7 @@ static void test_linked_units(const char *root) {
static void test_default(const char *root) {
_cleanup_free_ char *def = NULL;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
const char *p;
p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
@@ -351,7 +333,7 @@ static void test_default(const char *root) {
static void test_add_dependency(const char *root) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
const char *p;
p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
@@ -378,7 +360,7 @@ static void test_add_dependency(const char *root) {
static void test_template_enable(const char *root) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
UnitFileState state;
const char *p;
@@ -492,7 +474,7 @@ static void test_template_enable(const char *root) {
static void test_indirect(const char *root) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
UnitFileState state;
const char *p;
@@ -541,7 +523,7 @@ static void test_indirect(const char *root) {
static void test_preset_and_list(const char *root) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0, i;
+ size_t n_changes = 0, i;
const char *p, *q;
UnitFileState state;
bool got_yes = false, got_no = false;
@@ -651,7 +633,7 @@ static void test_revert(const char *root) {
const char *p;
UnitFileState state;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
assert(root);
@@ -700,7 +682,7 @@ static void test_revert(const char *root) {
static void test_preset_order(const char *root) {
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
const char *p;
UnitFileState state;
@@ -771,7 +753,7 @@ static void test_with_dropin(const char *root) {
const char *p;
UnitFileState state;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) == -ENOENT);
@@ -904,7 +886,7 @@ static void test_with_dropin_template(const char *root) {
const char *p;
UnitFileState state;
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) == -ENOENT);
diff --git a/src/test/test-install.c b/src/test/test-install.c
index 2f919187a9..7dfc7e4272 100644
--- a/src/test/test-install.c
+++ b/src/test/test-install.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
#include <string.h>
@@ -44,7 +26,7 @@ int main(int argc, char* argv[]) {
const char *const files[] = { "avahi-daemon.service", NULL };
const char *const files2[] = { "/home/lennart/test.service", NULL };
UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
+ size_t n_changes = 0;
UnitFileState state = 0;
log_set_max_level(LOG_DEBUG);
diff --git a/src/test/test-io-util.c b/src/test/test-io-util.c
index 9ed9864f29..42e632a8a2 100644
--- a/src/test/test-io-util.c
+++ b/src/test/test-io-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stdlib.h>
diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c
index c901e35841..106c29951e 100644
--- a/src/test/test-ipcrm.c
+++ b/src/test/test-ipcrm.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "clean-ipc.h"
#include "user-util.h"
diff --git a/src/test/test-job-type.c b/src/test/test-job-type.c
index 46444a0462..dc5f9eae83 100644
--- a/src/test/test-job-type.c
+++ b/src/test/test-job-type.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
@@ -96,6 +78,5 @@ int main(int argc, char*argv[]) {
}
}
-
return 0;
}
diff --git a/src/test/test-journal-importer.c b/src/test/test-journal-importer.c
index 931a281f54..56bf6a1296 100644
--- a/src/test/test-journal-importer.c
+++ b/src/test/test-journal-importer.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index f748fbc878..68399bdb9e 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
#include <stdio.h>
@@ -104,7 +86,7 @@ static void print_device(struct udev_device *device) {
}
static void test_device(struct udev *udev, const char *syspath) {
- _cleanup_udev_device_unref_ struct udev_device *device;
+ _cleanup_(udev_device_unrefp) struct udev_device *device;
log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
@@ -115,7 +97,7 @@ static void test_device(struct udev *udev, const char *syspath) {
}
static void test_device_parents(struct udev *udev, const char *syspath) {
- _cleanup_udev_device_unref_ struct udev_device *device;
+ _cleanup_(udev_device_unrefp) struct udev_device *device;
struct udev_device *device_parent;
log_info("looking at device: %s", syspath);
@@ -140,7 +122,7 @@ static void test_device_parents(struct udev *udev, const char *syspath) {
static void test_device_devnum(struct udev *udev) {
dev_t devnum = makedev(1, 3);
- _cleanup_udev_device_unref_ struct udev_device *device;
+ _cleanup_(udev_device_unrefp) struct udev_device *device;
log_info("looking up device: %u:%u", major(devnum), minor(devnum));
device = udev_device_new_from_devnum(udev, 'c', devnum);
@@ -151,7 +133,7 @@ static void test_device_devnum(struct udev *udev) {
}
static void test_device_subsys_name(struct udev *udev, const char *subsys, const char *dev) {
- _cleanup_udev_device_unref_ struct udev_device *device;
+ _cleanup_(udev_device_unrefp) struct udev_device *device;
log_info("looking up device: '%s:%s'", subsys, dev);
device = udev_device_new_from_subsystem_sysname(udev, subsys, dev);
@@ -183,7 +165,7 @@ static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
}
static void test_monitor(struct udev *udev) {
- _cleanup_udev_monitor_unref_ struct udev_monitor *udev_monitor;
+ _cleanup_(udev_monitor_unrefp) struct udev_monitor *udev_monitor;
_cleanup_close_ int fd_ep;
int fd_udev;
struct epoll_event ep_udev = {
@@ -350,7 +332,7 @@ static void test_hwdb(struct udev *udev, const char *modalias) {
}
int main(int argc, char *argv[]) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
bool arg_monitor = false;
static const struct option options[] = {
{ "syspath", required_argument, NULL, 'p' },
@@ -407,7 +389,6 @@ int main(int argc, char *argv[]) {
assert_not_reached("Unhandled option code.");
}
-
/* add sys path if needed */
if (!startswith(syspath, "/sys"))
syspath = strjoina("/sys/", syspath);
diff --git a/src/test/test-list.c b/src/test/test-list.c
index 25ffd8fb86..24e0496d46 100644
--- a/src/test/test-list.c
+++ b/src/test/test-list.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd
-
- Copyright 2013 Jan Janssen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Jan Janssen
***/
#include "list.h"
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 4467bdd48d..8ffae8ca03 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include "locale-util.h"
#include "macro.h"
@@ -39,6 +20,8 @@ static void test_get_locales(void) {
}
static void test_locale_is_valid(void) {
+ log_info("/* %s */", __func__);
+
assert_se(locale_is_valid("en_EN.utf8"));
assert_se(locale_is_valid("fr_FR.utf8"));
assert_se(locale_is_valid("fr_FR@euro"));
@@ -56,6 +39,8 @@ static void test_keymaps(void) {
char **p;
int r;
+ log_info("/* %s */", __func__);
+
assert_se(!keymap_is_valid(""));
assert_se(!keymap_is_valid("/usr/bin/foo"));
assert_se(!keymap_is_valid("\x01gar\x02 bage\x03"));
@@ -78,11 +63,31 @@ static void test_keymaps(void) {
assert_se(keymap_is_valid("unicode"));
}
+#define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x))
+static void dump_special_glyphs(void) {
+ assert_cc(ELLIPSIS + 1 == _SPECIAL_GLYPH_MAX);
+
+ log_info("/* %s */", __func__);
+
+ log_info("is_locale_utf8: %s", yes_no(is_locale_utf8()));
+
+ dump_glyph(TREE_VERTICAL);
+ dump_glyph(TREE_BRANCH);
+ dump_glyph(TREE_RIGHT);
+ dump_glyph(TREE_SPACE);
+ dump_glyph(TRIANGULAR_BULLET);
+ dump_glyph(BLACK_CIRCLE);
+ dump_glyph(ARROW);
+ dump_glyph(MDASH);
+ dump_glyph(ELLIPSIS);
+}
+
int main(int argc, char *argv[]) {
test_get_locales();
test_locale_is_valid();
-
test_keymaps();
+ dump_special_glyphs();
+
return 0;
}
diff --git a/src/test/test-log.c b/src/test/test-log.c
index 4a3c8955e3..c09f40c356 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
#include <unistd.h>
@@ -42,22 +24,19 @@ assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_USER | LOG_INFO) & LOG_PRIMA
static void test_log_console(void) {
log_struct(LOG_INFO,
"MESSAGE=Waldo PID="PID_FMT, getpid_cached(),
- "SERVICE=piepapo",
- NULL);
+ "SERVICE=piepapo");
}
static void test_log_journal(void) {
log_struct(LOG_INFO,
"MESSAGE=Foobar PID="PID_FMT, getpid_cached(),
- "SERVICE=foobar",
- NULL);
+ "SERVICE=foobar");
log_struct(LOG_INFO,
"MESSAGE=Foobar PID="PID_FMT, getpid_cached(),
"FORMAT_STR_TEST=1=%i A=%c 2=%hi 3=%li 4=%lli 1=%p foo=%s 2.5=%g 3.5=%g 4.5=%Lg",
(int) 1, 'A', (short) 2, (long int) 3, (long long int) 4, (void*) 1, "foo", (float) 2.5f, (double) 3.5, (long double) 4.5,
- "SUFFIX=GOT IT",
- NULL);
+ "SUFFIX=GOT IT");
}
static void test_long_lines(void) {
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
index 3fe897ac08..eaea9e4c76 100644
--- a/src/test/test-loopback.c
+++ b/src/test/test-loopback.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
#include <string.h>
diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c
index 5f2ad7c719..c10e1681fb 100644
--- a/src/test/test-mount-util.c
+++ b/src/test/test-mount-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/mount.h>
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index 3b84b01961..b202739719 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/socket.h>
diff --git a/src/test/test-netlink-manual.c b/src/test/test-netlink-manual.c
index 3b10b697af..eed610b27a 100644
--- a/src/test/test-netlink-manual.c
+++ b/src/test/test-netlink-manual.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Susant Sahani
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <arpa/inet.h>
#include <libkmod.h>
diff --git a/src/test/test-ns.c b/src/test/test-ns.c
index 3ab3c1ab95..4ab70f2306 100644
--- a/src/test/test-ns.c
+++ b/src/test/test-ns.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdlib.h>
diff --git a/src/test/test-nss.c b/src/test/test-nss.c
index acfb6760a9..9e543e7557 100644
--- a/src/test/test-nss.c
+++ b/src/test/test-nss.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <dlfcn.h>
#include <stdlib.h>
@@ -100,7 +82,7 @@ static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) {
r = in_addr_to_string(it->family, &u, &a);
assert_se(IN_SET(r, 0, -EAFNOSUPPORT));
if (r == -EAFNOSUPPORT)
- assert_se((a = hexmem(it->addr, 16)));
+ assert_se(a = hexmem(it->addr, 16));
if (it->scopeid == 0)
goto numerical_index;
@@ -194,7 +176,6 @@ static void test_gethostbyname4_r(void *handle, const char *module, const char *
}
}
-
static void test_gethostbyname3_r(void *handle, const char *module, const char *name, int af) {
const char *fname;
_nss_gethostbyname3_r_t f;
@@ -414,7 +395,6 @@ static int test_one_module(const char* dir,
char **name;
int i;
-
log_info("======== %s ========", module);
handle = open_handle(streq(module, "dns") ? NULL : dir,
diff --git a/src/test/test-os-util.c b/src/test/test-os-util.c
new file mode 100644
index 0000000000..8d8b52d7f6
--- /dev/null
+++ b/src/test/test-os-util.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "log.h"
+#include "os-util.h"
+
+static void test_path_is_os_tree(void) {
+ assert_se(path_is_os_tree("/") > 0);
+ assert_se(path_is_os_tree("/etc") == 0);
+ assert_se(path_is_os_tree("/idontexist") == -ENOENT);
+}
+
+int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_path_is_os_tree();
+
+ return 0;
+}
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
index a99cea5a14..e9aef5e882 100644
--- a/src/test/test-parse-util.c
+++ b/src/test/test-parse-util.c
@@ -1,27 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <locale.h>
#include <math.h>
+#include <sys/socket.h>
#include "alloc-util.h"
#include "errno-list.h"
@@ -660,6 +642,54 @@ static void test_parse_percent_unbounded(void) {
assert_se(parse_percent_unbounded("400%") == 400);
}
+static void test_parse_permille(void) {
+ assert_se(parse_permille("") == -EINVAL);
+ assert_se(parse_permille("foo") == -EINVAL);
+ assert_se(parse_permille("0") == -EINVAL);
+ assert_se(parse_permille("50") == -EINVAL);
+ assert_se(parse_permille("100") == -EINVAL);
+ assert_se(parse_permille("-1") == -EINVAL);
+
+ assert_se(parse_permille("0‰") == 0);
+ assert_se(parse_permille("555‰") == 555);
+ assert_se(parse_permille("1000‰") == 1000);
+ assert_se(parse_permille("-7‰") == -ERANGE);
+ assert_se(parse_permille("1007‰") == -ERANGE);
+ assert_se(parse_permille("‰") == -EINVAL);
+ assert_se(parse_permille("‰‰") == -EINVAL);
+ assert_se(parse_permille("‰1") == -EINVAL);
+ assert_se(parse_permille("1‰‰") == -EINVAL);
+ assert_se(parse_permille("3.2‰") == -EINVAL);
+
+ assert_se(parse_permille("0%") == 0);
+ assert_se(parse_permille("55%") == 550);
+ assert_se(parse_permille("55.5%") == 555);
+ assert_se(parse_permille("100%") == 1000);
+ assert_se(parse_permille("-7%") == -ERANGE);
+ assert_se(parse_permille("107%") == -ERANGE);
+ assert_se(parse_permille("%") == -EINVAL);
+ assert_se(parse_permille("%%") == -EINVAL);
+ assert_se(parse_permille("%1") == -EINVAL);
+ assert_se(parse_permille("1%%") == -EINVAL);
+ assert_se(parse_permille("3.21%") == -EINVAL);
+}
+
+static void test_parse_permille_unbounded(void) {
+ assert_se(parse_permille_unbounded("1001‰") == 1001);
+ assert_se(parse_permille_unbounded("4000‰") == 4000);
+ assert_se(parse_permille_unbounded("2147483647‰") == 2147483647);
+ assert_se(parse_permille_unbounded("2147483648‰") == -ERANGE);
+ assert_se(parse_permille_unbounded("4294967295‰") == -ERANGE);
+ assert_se(parse_permille_unbounded("4294967296‰") == -ERANGE);
+
+ assert_se(parse_permille_unbounded("101%") == 1010);
+ assert_se(parse_permille_unbounded("400%") == 4000);
+ assert_se(parse_permille_unbounded("214748364.7%") == 2147483647);
+ assert_se(parse_permille_unbounded("214748364.8%") == -ERANGE);
+ assert_se(parse_permille_unbounded("429496729.5%") == -ERANGE);
+ assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE);
+}
+
static void test_parse_nice(void) {
int n;
@@ -675,7 +705,6 @@ static void test_parse_nice(void) {
assert_se(parse_nice("19", &n) >= 0 && n == 19);
assert_se(parse_nice("+19", &n) >= 0 && n == 19);
-
assert_se(parse_nice("", &n) == -EINVAL);
assert_se(parse_nice("-", &n) == -EINVAL);
assert_se(parse_nice("+", &n) == -EINVAL);
@@ -771,6 +800,27 @@ static void test_parse_syscall_and_errno(void) {
assert_se(parse_syscall_and_errno("hoge:", &n, &e) == -EINVAL);
}
+static void test_parse_mtu(void) {
+ uint32_t mtu = 0;
+
+ assert_se(parse_mtu(AF_UNSPEC, "1500", &mtu) >= 0 && mtu == 1500);
+ assert_se(parse_mtu(AF_UNSPEC, "1400", &mtu) >= 0 && mtu == 1400);
+ assert_se(parse_mtu(AF_UNSPEC, "65535", &mtu) >= 0 && mtu == 65535);
+ assert_se(parse_mtu(AF_UNSPEC, "65536", &mtu) >= 0 && mtu == 65536);
+ assert_se(parse_mtu(AF_UNSPEC, "4294967295", &mtu) >= 0 && mtu == 4294967295);
+ assert_se(parse_mtu(AF_UNSPEC, "500", &mtu) >= 0 && mtu == 500);
+ assert_se(parse_mtu(AF_UNSPEC, "1280", &mtu) >= 0 && mtu == 1280);
+ assert_se(parse_mtu(AF_INET6, "1280", &mtu) >= 0 && mtu == 1280);
+ assert_se(parse_mtu(AF_INET6, "1279", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_UNSPEC, "4294967296", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_INET6, "4294967296", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_INET6, "68", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_UNSPEC, "68", &mtu) >= 0 && mtu == 68);
+ assert_se(parse_mtu(AF_UNSPEC, "67", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_UNSPEC, "0", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_UNSPEC, "", &mtu) == -EINVAL);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -789,10 +839,13 @@ int main(int argc, char *argv[]) {
test_safe_atod();
test_parse_percent();
test_parse_percent_unbounded();
+ test_parse_permille();
+ test_parse_permille_unbounded();
test_parse_nice();
test_parse_dev();
test_parse_errno();
test_parse_syscall_and_errno();
+ test_parse_mtu();
return 0;
}
diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c
index 0541033d77..892293cb10 100644
--- a/src/test/test-path-lookup.c
+++ b/src/test/test-path-lookup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdlib.h>
#include <sys/stat.h>
@@ -30,8 +12,8 @@
static void test_paths(UnitFileScope scope) {
char template[] = "/tmp/test-path-lookup.XXXXXXX";
- _cleanup_lookup_paths_free_ LookupPaths lp_without_env = {};
- _cleanup_lookup_paths_free_ LookupPaths lp_with_env = {};
+ _cleanup_(lookup_paths_free) LookupPaths lp_without_env = {};
+ _cleanup_(lookup_paths_free) LookupPaths lp_with_env = {};
char *systemd_unit_path;
assert_se(mkdtemp(template));
@@ -53,7 +35,7 @@ static void test_paths(UnitFileScope scope) {
}
static void test_user_and_global_paths(void) {
- _cleanup_lookup_paths_free_ LookupPaths lp_global = {}, lp_user = {};
+ _cleanup_(lookup_paths_free) LookupPaths lp_global = {}, lp_user = {};
char **u, **g, **p;
unsigned k = 0;
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 0db835608a..35b27bcedd 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
#include <unistd.h>
@@ -39,6 +21,16 @@
assert_se(path_equal(b, a) == !result); \
}
+static void test_path_simplify(const char *in, const char *out, const char *out_dot) {
+ char *p;
+
+ p = strdupa(in);
+ assert_se(streq(path_simplify(p, false), out));
+
+ p = strdupa(in);
+ assert_se(streq(path_simplify(p, true), out_dot));
+}
+
static void test_path(void) {
_cleanup_close_ int fd = -1;
@@ -82,15 +74,28 @@ static void test_path(void) {
assert_se(fd >= 0);
assert_se(fd_is_mount_point(fd, "/", 0) > 0);
- {
- char p1[] = "aaa/bbb////ccc";
- char p2[] = "//aaa/.////ccc";
- char p3[] = "/./";
-
- assert_se(path_equal(path_kill_slashes(p1), "aaa/bbb/ccc"));
- assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc"));
- assert_se(path_equal(path_kill_slashes(p3), "/./"));
- }
+ test_path_simplify("aaa/bbb////ccc", "aaa/bbb/ccc", "aaa/bbb/ccc");
+ test_path_simplify("//aaa/.////ccc", "/aaa/./ccc", "/aaa/ccc");
+ test_path_simplify("///", "/", "/");
+ test_path_simplify("///.//", "/.", "/");
+ test_path_simplify("///.//.///", "/./.", "/");
+ test_path_simplify("////.././///../.", "/.././../.", "/../..");
+ test_path_simplify(".", ".", "");
+ test_path_simplify("./", ".", "");
+ test_path_simplify(".///.//./.", "./././.", "");
+ test_path_simplify(".///.//././/", "./././.", "");
+ test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.",
+ "/./aaa/././.bbb/../c./d.dd/..eeee/.",
+ "/aaa/.bbb/../c./d.dd/..eeee");
+ test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
+ "/./aaa/././.bbb/../c./d.dd/..eeee/..",
+ "/aaa/.bbb/../c./d.dd/..eeee/..");
+ test_path_simplify(".//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
+ "././aaa/././.bbb/../c./d.dd/..eeee/..",
+ "aaa/.bbb/../c./d.dd/..eeee/..");
+ test_path_simplify("..//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
+ ".././aaa/././.bbb/../c./d.dd/..eeee/..",
+ "../aaa/.bbb/../c./d.dd/..eeee/..");
assert_se(PATH_IN_SET("/bin", "/", "/bin", "/foo"));
assert_se(PATH_IN_SET("/bin", "/bin"));
@@ -276,7 +281,7 @@ static void test_make_relative(void) {
test("/some/path", "/", "../..");
test("/some/path", "/some/other/path", "../other/path");
test("/some/path/./dot", "/some/further/path", "../../further/path");
- test("//extra/////slashes///won't////fool///anybody//", "////extra///slashes////are/just///fine///", "../../../are/just/fine");
+ test("//extra.//.//./.slashes//./won't////fo.ol///anybody//", "/././/extra././/.slashes////ar.e/.just/././.fine///", "../../../ar.e/.just/.fine");
}
static void test_strv_resolve(void) {
@@ -412,6 +417,10 @@ static void test_last_path_component(void) {
assert_se(streq(last_path_component("/foo/a"), "a"));
assert_se(streq(last_path_component("/foo/a/"), "a/"));
assert_se(streq(last_path_component(""), ""));
+ assert_se(streq(last_path_component("a"), "a"));
+ assert_se(streq(last_path_component("a/"), "a/"));
+ assert_se(streq(last_path_component("/a"), "a"));
+ assert_se(streq(last_path_component("/a/"), "a/"));
}
static void test_filename_is_valid(void) {
@@ -483,6 +492,19 @@ static void test_skip_dev_prefix(void) {
assert_se(streq(skip_dev_prefix("foo"), "foo"));
}
+static void test_empty_or_root(void) {
+ assert_se(empty_or_root(NULL));
+ assert_se(empty_or_root(""));
+ assert_se(empty_or_root("/"));
+ assert_se(empty_or_root("//"));
+ assert_se(empty_or_root("///"));
+ assert_se(empty_or_root("/////////////////"));
+ assert_se(!empty_or_root("xxx"));
+ assert_se(!empty_or_root("/xxx"));
+ assert_se(!empty_or_root("/xxx/"));
+ assert_se(!empty_or_root("//yy//"));
+}
+
int main(int argc, char **argv) {
log_set_max_level(LOG_DEBUG);
log_parse_environment();
@@ -503,6 +525,7 @@ int main(int argc, char **argv) {
test_filename_is_valid();
test_hidden_or_backup_file();
test_skip_dev_prefix();
+ test_empty_or_root();
test_systemd_installation_has_version(argv[1]); /* NULL is OK */
diff --git a/src/test/test-path.c b/src/test/test-path.c
index 3f579b064d..209eb2e366 100644
--- a/src/test/test-path.c
+++ b/src/test/test-path.c
@@ -1,27 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "alloc-util.h"
+#include "all-units.h"
#include "fd-util.h"
#include "fs-util.h"
#include "macro.h"
@@ -52,7 +37,7 @@ static int setup_test(Manager **m) {
return -EXIT_TEST_SKIP;
}
- r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &tmp);
+ r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &tmp);
if (MANAGER_SKIP_TEST(r)) {
log_notice_errno(r, "Skipping test: manager_new: %m");
return -EXIT_TEST_SKIP;
@@ -113,7 +98,6 @@ static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, con
service_state_to_string(service->state),
service_result_to_string(service->result));
-
/* But we timeout if the service has not been started in the allocated time */
n = now(CLOCK_MONOTONIC);
if (ts + timeout < n) {
@@ -132,7 +116,7 @@ static void test_path_exists(Manager *m) {
assert_se(m);
- assert_se(manager_load_unit(m, "path-exists.path", NULL, NULL, &unit) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "path-exists.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
assert_se(touch(test_path) >= 0);
@@ -145,7 +129,7 @@ static void test_path_existsglob(Manager *m) {
Unit *unit = NULL;
assert_se(m);
- assert_se(manager_load_unit(m, "path-existsglob.path", NULL, NULL, &unit) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "path-existsglob.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
assert_se(touch(test_path) >= 0);
@@ -162,7 +146,7 @@ static void test_path_changed(Manager *m) {
assert_se(touch(test_path) >= 0);
- assert_se(manager_load_unit(m, "path-changed.path", NULL, NULL, &unit) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "path-changed.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
f = fopen(test_path, "w");
@@ -181,7 +165,7 @@ static void test_path_modified(Manager *m) {
assert_se(touch(test_path) >= 0);
- assert_se(manager_load_unit(m, "path-modified.path", NULL, NULL, &unit) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "path-modified.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
f = fopen(test_path, "w");
@@ -197,7 +181,7 @@ static void test_path_unit(Manager *m) {
assert_se(m);
- assert_se(manager_load_unit(m, "path-unit.path", NULL, NULL, &unit) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "path-unit.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
assert_se(touch(test_path) >= 0);
@@ -213,7 +197,7 @@ static void test_path_directorynotempty(Manager *m) {
assert_se(access(test_path, F_OK) < 0);
- assert_se(manager_load_unit(m, "path-directorynotempty.path", NULL, NULL, &unit) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "path-directorynotempty.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
/* MakeDirectory default to no */
@@ -234,7 +218,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
assert_se(access(test_path, F_OK) < 0);
- assert_se(manager_load_unit(m, "path-makedirectory.path", NULL, NULL, &unit) >= 0);
+ assert_se(manager_load_startable_unit_or_warn(m, "path-makedirectory.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
/* Check if the directory has been created */
@@ -266,6 +250,8 @@ int main(int argc, char *argv[]) {
const test_function_t *test = NULL;
Manager *m = NULL;
+ umask(022);
+
log_parse_environment();
log_open();
diff --git a/src/test/test-prioq.c b/src/test/test-prioq.c
index f558384a18..89c41d8ce7 100644
--- a/src/test/test-prioq.c
+++ b/src/test/test-prioq.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdlib.h>
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
index 01b8cf0ca7..8f77e084b6 100644
--- a/src/test/test-proc-cmdline.c
+++ b/src/test/test-proc-cmdline.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "log.h"
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 1a0164e601..fd4d17408d 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sched.h>
#include <sys/mount.h>
@@ -104,6 +85,38 @@ static void test_get_process_comm(pid_t pid) {
log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
}
+static void test_get_process_comm_escape_one(const char *input, const char *output) {
+ _cleanup_free_ char *n = NULL;
+
+ log_info("input: <%s> — output: <%s>", input, output);
+
+ assert_se(prctl(PR_SET_NAME, input) >= 0);
+ assert_se(get_process_comm(0, &n) >= 0);
+
+ log_info("got: <%s>", n);
+
+ assert_se(streq_ptr(n, output));
+}
+
+static void test_get_process_comm_escape(void) {
+ _cleanup_free_ char *saved = NULL;
+
+ assert_se(get_process_comm(0, &saved) >= 0);
+
+ test_get_process_comm_escape_one("", "");
+ test_get_process_comm_escape_one("foo", "foo");
+ test_get_process_comm_escape_one("012345678901234", "012345678901234");
+ test_get_process_comm_escape_one("0123456789012345", "012345678901234");
+ test_get_process_comm_escape_one("äöüß", "\\303\\244\\303…");
+ test_get_process_comm_escape_one("xäöüß", "x\\303\\244…");
+ test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244…");
+ test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244…");
+ test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244…");
+ test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303…");
+
+ assert_se(prctl(PR_SET_NAME, saved) >= 0);
+}
+
static void test_pid_is_unwaited(void) {
pid_t pid;
@@ -379,7 +392,7 @@ static void test_rename_process_now(const char *p, int ret) {
assert_se(get_process_comm(0, &comm) >= 0);
log_info("comm = <%s>", comm);
- assert_se(strneq(comm, p, 15));
+ assert_se(strneq(comm, p, TASK_COMM_LEN-1));
assert_se(get_process_cmdline(0, 0, false, &cmdline) >= 0);
/* we cannot expect cmdline to be renamed properly without privileges */
@@ -541,8 +554,33 @@ static void test_pid_to_ptr(void) {
#endif
}
-int main(int argc, char *argv[]) {
+static void test_ioprio_class_from_to_string_one(const char *val, int expected) {
+ assert_se(ioprio_class_from_string(val) == expected);
+ if (expected >= 0) {
+ _cleanup_free_ char *s = NULL;
+ unsigned ret;
+ assert_se(ioprio_class_to_string_alloc(expected, &s) == 0);
+ /* We sometimes get a class number and sometimes a number back */
+ assert_se(streq(s, val) ||
+ safe_atou(val, &ret) == 0);
+ }
+}
+
+static void test_ioprio_class_from_to_string(void) {
+ test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE);
+ test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT);
+ test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE);
+ test_ioprio_class_from_to_string_one("idle", IOPRIO_CLASS_IDLE);
+ test_ioprio_class_from_to_string_one("0", 0);
+ test_ioprio_class_from_to_string_one("1", 1);
+ test_ioprio_class_from_to_string_one("7", 7);
+ test_ioprio_class_from_to_string_one("8", 8);
+ test_ioprio_class_from_to_string_one("9", -1);
+ test_ioprio_class_from_to_string_one("-1", -1);
+}
+
+int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
log_parse_environment();
log_open();
@@ -560,6 +598,7 @@ int main(int argc, char *argv[]) {
test_get_process_comm(getpid());
}
+ test_get_process_comm_escape();
test_pid_is_unwaited();
test_pid_is_alive();
test_personality();
@@ -569,6 +608,7 @@ int main(int argc, char *argv[]) {
test_getpid_measure();
test_safe_fork();
test_pid_to_ptr();
+ test_ioprio_class_from_to_string();
return 0;
}
diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c
index 10229de4e8..08af380cc7 100644
--- a/src/test/test-procfs-util.c
+++ b/src/test/test-procfs-util.c
@@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
log_open();
assert_se(procfs_cpu_get_usage(&nsec) >= 0);
- log_info("Current sytem CPU time: %s", format_timespan(buf, sizeof(buf), nsec/NSEC_PER_USEC, 1));
+ log_info("Current system CPU time: %s", format_timespan(buf, sizeof(buf), nsec/NSEC_PER_USEC, 1));
assert_se(procfs_memory_get_current(&v) >= 0);
log_info("Current memory usage: %s", format_bytes(buf, sizeof(buf), v));
diff --git a/src/test/test-random-util.c b/src/test/test-random-util.c
index d7ccc91f9b..a4760b54a3 100644
--- a/src/test/test-random-util.c
+++ b/src/test/test-random-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "hexdecoct.h"
#include "random-util.h"
diff --git a/src/test/test-ratelimit.c b/src/test/test-ratelimit.c
index dcfa60e94d..9f344e1152 100644
--- a/src/test/test-ratelimit.c
+++ b/src/test/test-ratelimit.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <unistd.h>
@@ -24,24 +6,24 @@
#include "ratelimit.h"
#include "time-util.h"
-static void test_ratelimit_test(void) {
+static void test_ratelimit_below(void) {
int i;
RATELIMIT_DEFINE(ratelimit, 1 * USEC_PER_SEC, 10);
for (i = 0; i < 10; i++)
- assert_se(ratelimit_test(&ratelimit));
- assert_se(!ratelimit_test(&ratelimit));
+ assert_se(ratelimit_below(&ratelimit));
+ assert_se(!ratelimit_below(&ratelimit));
sleep(1);
for (i = 0; i < 10; i++)
- assert_se(ratelimit_test(&ratelimit));
+ assert_se(ratelimit_below(&ratelimit));
RATELIMIT_INIT(ratelimit, 0, 10);
for (i = 0; i < 10000; i++)
- assert_se(ratelimit_test(&ratelimit));
+ assert_se(ratelimit_below(&ratelimit));
}
int main(int argc, char *argv[]) {
- test_ratelimit_test();
+ test_ratelimit_below();
return 0;
}
diff --git a/src/test/test-replace-var.c b/src/test/test-replace-var.c
index 56ce99e7ac..55208b179f 100644
--- a/src/test/test-replace-var.c
+++ b/src/test/test-replace-var.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
diff --git a/src/test/test-rlimit-util.c b/src/test/test-rlimit-util.c
index 93724434a5..15701b2712 100644
--- a/src/test/test-rlimit-util.c
+++ b/src/test/test-rlimit-util.c
@@ -1,20 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/resource.h>
@@ -55,6 +39,7 @@ int main(int argc, char *argv[]) {
.rlim_cur = 10,
.rlim_max = 5,
};
+ int i;
log_parse_environment();
log_open();
@@ -66,10 +51,41 @@ int main(int argc, char *argv[]) {
new.rlim_max = old.rlim_max;
assert_se(setrlimit(RLIMIT_NOFILE, &new) >= 0);
- assert_se(rlimit_from_string("LimitNOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string("NOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string("LimitNOFILE") == -1);
+ assert_se(rlimit_from_string("RLIMIT_NOFILE") == -1);
+ assert_se(rlimit_from_string("xxxNOFILE") == -1);
assert_se(rlimit_from_string("DefaultLimitNOFILE") == -1);
- assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "LimitNOFILE"));
+ assert_se(rlimit_from_string_harder("NOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string_harder("LimitNOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string_harder("RLIMIT_NOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string_harder("xxxNOFILE") == -1);
+ assert_se(rlimit_from_string_harder("DefaultLimitNOFILE") == -1);
+
+ for (i = 0; i < _RLIMIT_MAX; i++) {
+ _cleanup_free_ char *prefixed = NULL;
+ const char *p;
+
+ assert_se(p = rlimit_to_string(i));
+ log_info("%i = %s", i, p);
+
+ assert_se(rlimit_from_string(p) == i);
+ assert_se(rlimit_from_string_harder(p) == i);
+
+ assert_se(prefixed = strjoin("Limit", p));
+
+ assert_se(rlimit_from_string(prefixed) < 0);
+ assert_se(rlimit_from_string_harder(prefixed) == i);
+
+ prefixed = mfree(prefixed);
+ assert_se(prefixed = strjoin("RLIMIT_", p));
+
+ assert_se(rlimit_from_string(prefixed) < 0);
+ assert_se(rlimit_from_string_harder(prefixed) == i);
+ }
+
+ assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "NOFILE"));
assert_se(rlimit_to_string(-1) == NULL);
assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c
index 804cee34e9..c986284155 100644
--- a/src/test/test-sched-prio.c
+++ b/src/test/test-sched-prio.c
@@ -1,25 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2012 Holger Hans Peter Freyther
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2012 Holger Hans Peter Freyther
***/
#include <sched.h>
+#include "all-units.h"
#include "macro.h"
#include "manager.h"
#include "rm-rf.h"
@@ -28,11 +14,9 @@
int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
- Manager *m = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
Unit *idle_ok, *idle_bad, *rr_ok, *rr_bad, *rr_sched;
Service *ser;
- FILE *serial = NULL;
- FDSet *fdset = NULL;
int r;
r = enter_cgroup_subroot();
@@ -44,17 +28,16 @@ int main(int argc, char *argv[]) {
/* prepare the test */
assert_se(set_unit_path(get_testdata_dir("")) >= 0);
assert_se(runtime_dir = setup_fake_runtime_dir());
- r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
+ r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m);
if (MANAGER_SKIP_TEST(r)) {
log_notice_errno(r, "Skipping test: manager_new: %m");
return EXIT_TEST_SKIP;
}
assert_se(r >= 0);
- assert_se(manager_startup(m, serial, fdset) >= 0);
+ assert_se(manager_startup(m, NULL, NULL) >= 0);
/* load idle ok */
- assert_se(manager_load_unit(m, "sched_idle_ok.service", NULL, NULL, &idle_ok) >= 0);
- assert_se(idle_ok->load_state == UNIT_LOADED);
+ assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_ok.service", NULL, &idle_ok) >= 0);
ser = SERVICE(idle_ok);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER);
assert_se(ser->exec_context.cpu_sched_priority == 0);
@@ -62,8 +45,7 @@ int main(int argc, char *argv[]) {
/*
* load idle bad. This should print a warning but we have no way to look at it.
*/
- assert_se(manager_load_unit(m, "sched_idle_bad.service", NULL, NULL, &idle_bad) >= 0);
- assert_se(idle_bad->load_state == UNIT_LOADED);
+ assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_bad.service", NULL, &idle_bad) >= 0);
ser = SERVICE(idle_ok);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER);
assert_se(ser->exec_context.cpu_sched_priority == 0);
@@ -72,8 +54,7 @@ int main(int argc, char *argv[]) {
* load rr ok.
* Test that the default priority is moving from 0 to 1.
*/
- assert_se(manager_load_unit(m, "sched_rr_ok.service", NULL, NULL, &rr_ok) >= 0);
- assert_se(rr_ok->load_state == UNIT_LOADED);
+ assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_ok.service", NULL, &rr_ok) >= 0);
ser = SERVICE(rr_ok);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
assert_se(ser->exec_context.cpu_sched_priority == 1);
@@ -82,8 +63,7 @@ int main(int argc, char *argv[]) {
* load rr bad.
* Test that the value of 0 and 100 is ignored.
*/
- assert_se(manager_load_unit(m, "sched_rr_bad.service", NULL, NULL, &rr_bad) >= 0);
- assert_se(rr_bad->load_state == UNIT_LOADED);
+ assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_bad.service", NULL, &rr_bad) >= 0);
ser = SERVICE(rr_bad);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
assert_se(ser->exec_context.cpu_sched_priority == 1);
@@ -92,13 +72,10 @@ int main(int argc, char *argv[]) {
* load rr change.
* Test that anything between 1 and 99 can be set.
*/
- assert_se(manager_load_unit(m, "sched_rr_change.service", NULL, NULL, &rr_sched) >= 0);
- assert_se(rr_sched->load_state == UNIT_LOADED);
+ assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_change.service", NULL, &rr_sched) >= 0);
ser = SERVICE(rr_sched);
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-seccomp.c b/src/test/test-seccomp.c
index aed307077e..d82cb5c1c5 100644
--- a/src/test/test-seccomp.c
+++ b/src/test/test-seccomp.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <poll.h>
#include <sched.h>
@@ -122,7 +104,8 @@ static void test_filter_sets(void) {
if (pid == 0) { /* Child? */
int fd;
- if (i == SYSCALL_FILTER_SET_DEFAULT) /* if we look at the default set, whitelist instead of blacklist */
+ /* if we look at the default set (or one that includes it), whitelist instead of blacklist */
+ if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE))
r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW);
else
r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN));
@@ -146,29 +129,36 @@ static void test_filter_sets(void) {
}
static void test_restrict_namespace(void) {
- _cleanup_free_ char *s = NULL;
+ char *s = NULL;
unsigned long ul;
pid_t pid;
- assert_se(namespace_flag_to_string(0) == NULL);
- assert_se(streq(namespace_flag_to_string(CLONE_NEWNS), "mnt"));
- assert_se(namespace_flag_to_string(CLONE_NEWNS|CLONE_NEWIPC) == NULL);
- assert_se(streq(namespace_flag_to_string(CLONE_NEWCGROUP), "cgroup"));
-
- assert_se(namespace_flag_from_string("mnt") == CLONE_NEWNS);
- assert_se(namespace_flag_from_string(NULL) == 0);
- assert_se(namespace_flag_from_string("") == 0);
- assert_se(namespace_flag_from_string("uts") == CLONE_NEWUTS);
- assert_se(namespace_flag_from_string(namespace_flag_to_string(CLONE_NEWUTS)) == CLONE_NEWUTS);
- assert_se(streq(namespace_flag_to_string(namespace_flag_from_string("ipc")), "ipc"));
-
- assert_se(namespace_flag_from_string_many(NULL, &ul) == 0 && ul == 0);
- assert_se(namespace_flag_from_string_many("", &ul) == 0 && ul == 0);
- assert_se(namespace_flag_from_string_many("mnt uts ipc", &ul) == 0 && ul == (CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC));
-
- assert_se(namespace_flag_to_string_many(NAMESPACE_FLAGS_ALL, &s) == 0);
+ assert_se(namespace_flags_to_string(0, &s) == 0 && streq(s, ""));
+ s = mfree(s);
+ assert_se(namespace_flags_to_string(CLONE_NEWNS, &s) == 0 && streq(s, "mnt"));
+ s = mfree(s);
+ assert_se(namespace_flags_to_string(CLONE_NEWNS|CLONE_NEWIPC, &s) == 0 && streq(s, "ipc mnt"));
+ s = mfree(s);
+ assert_se(namespace_flags_to_string(CLONE_NEWCGROUP, &s) == 0 && streq(s, "cgroup"));
+ s = mfree(s);
+
+ assert_se(namespace_flags_from_string("mnt", &ul) == 0 && ul == CLONE_NEWNS);
+ assert_se(namespace_flags_from_string(NULL, &ul) == 0 && ul == 0);
+ assert_se(namespace_flags_from_string("", &ul) == 0 && ul == 0);
+ assert_se(namespace_flags_from_string("uts", &ul) == 0 && ul == CLONE_NEWUTS);
+ assert_se(namespace_flags_from_string("mnt uts ipc", &ul) == 0 && ul == (CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC));
+
+ assert_se(namespace_flags_to_string(CLONE_NEWUTS, &s) == 0 && streq(s, "uts"));
+ assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == CLONE_NEWUTS);
+ s = mfree(s);
+ assert_se(namespace_flags_from_string("ipc", &ul) == 0 && ul == CLONE_NEWIPC);
+ assert_se(namespace_flags_to_string(ul, &s) == 0 && streq(s, "ipc"));
+ s = mfree(s);
+
+ assert_se(namespace_flags_to_string(NAMESPACE_FLAGS_ALL, &s) == 0);
assert_se(streq(s, "cgroup ipc net mnt pid user uts"));
- assert_se(namespace_flag_from_string_many(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL);
+ assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL);
+ s = mfree(s);
if (!is_seccomp_available())
return;
diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c
index f954dbb456..6caeb843f3 100644
--- a/src/test/test-selinux.c
+++ b/src/test/test-selinux.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/stat.h>
diff --git a/src/test/test-set.c b/src/test/test-set.c
index 0a29a62621..6307403e4c 100644
--- a/src/test/test-set.c
+++ b/src/test/test-set.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "set.h"
@@ -79,55 +61,10 @@ static void test_set_put(void) {
assert_se(set_put(m, (void*) "22") == 0);
}
-static void test_set_make(void) {
- _cleanup_set_free_ Set *s = NULL;
-
- assert_se(set_make(&s, NULL, UINT_TO_PTR(4), UINT_TO_PTR(6), UINT_TO_PTR(8), NULL) == 0);
- assert_se(set_size(s) == 3);
- assert_se(!set_contains(s, UINT_TO_PTR(0)));
- assert_se(!set_contains(s, UINT_TO_PTR(1)));
- assert_se(!set_contains(s, UINT_TO_PTR(2)));
- assert_se(!set_contains(s, UINT_TO_PTR(3)));
- assert_se(set_contains(s, UINT_TO_PTR(4)));
- assert_se(!set_contains(s, UINT_TO_PTR(5)));
- assert_se(set_contains(s, UINT_TO_PTR(6)));
- assert_se(!set_contains(s, UINT_TO_PTR(7)));
- assert_se(set_contains(s, UINT_TO_PTR(8)));
- assert_se(!set_contains(s, UINT_TO_PTR(9)));
- s = set_free(s);
-
- assert_se(set_make(&s, NULL, NULL) == 0);
- assert_se(set_size(s) == 0);
- assert_se(!set_contains(s, UINT_TO_PTR(0)));
- assert_se(!set_contains(s, UINT_TO_PTR(4)));
- assert_se(!set_contains(s, UINT_TO_PTR(6)));
- assert_se(!set_contains(s, UINT_TO_PTR(8)));
- s = set_free(s);
-
- assert_se(set_make(&s, NULL, UINT_TO_PTR(3), NULL) == 0);
- assert_se(set_size(s) == 1);
- assert_se(!set_contains(s, UINT_TO_PTR(0)));
- assert_se(!set_contains(s, UINT_TO_PTR(1)));
- assert_se(!set_contains(s, UINT_TO_PTR(2)));
- assert_se(set_contains(s, UINT_TO_PTR(3)));
- assert_se(!set_contains(s, UINT_TO_PTR(4)));
-
- assert_se(set_make(&s, NULL, UINT_TO_PTR(2), UINT_TO_PTR(5), NULL) == 0);
- assert_se(set_size(s) == 2);
- assert_se(!set_contains(s, UINT_TO_PTR(0)));
- assert_se(!set_contains(s, UINT_TO_PTR(1)));
- assert_se(set_contains(s, UINT_TO_PTR(2)));
- assert_se(!set_contains(s, UINT_TO_PTR(3)));
- assert_se(!set_contains(s, UINT_TO_PTR(4)));
- assert_se(set_contains(s, UINT_TO_PTR(5)));
- assert_se(!set_contains(s, UINT_TO_PTR(6)));
-}
-
int main(int argc, const char *argv[]) {
test_set_steal_first();
test_set_free_with_destructor();
test_set_put();
- test_set_make();
return 0;
}
diff --git a/src/test/test-sigbus.c b/src/test/test-sigbus.c
index 75df8513f1..c9343364d4 100644
--- a/src/test/test-sigbus.c
+++ b/src/test/test-sigbus.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/mman.h>
diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c
index f4b19ed69d..8ea4163790 100644
--- a/src/test/test-signal-util.c
+++ b/src/test/test-signal-util.c
@@ -1,30 +1,110 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <signal.h>
#include <unistd.h>
+#include "log.h"
#include "macro.h"
#include "signal-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
#include "process-util.h"
+#define info(sig) log_info(#sig " = " STRINGIFY(sig) " = %d", sig)
+
+static void test_rt_signals(void) {
+ info(SIGRTMIN);
+ info(SIGRTMAX);
+
+ /* We use signals SIGRTMIN+0 to SIGRTMIN+24 unconditionally */
+ assert(SIGRTMAX - SIGRTMIN >= 24);
+}
+
+static void test_signal_to_string_one(int val) {
+ const char *p;
+
+ assert_se(p = signal_to_string(val));
+
+ assert_se(signal_from_string(p) == val);
+
+ p = strjoina("SIG", p);
+ assert_se(signal_from_string(p) == val);
+}
+
+static void test_signal_from_string_one(const char *s, int val) {
+ const char *p;
+
+ assert_se(signal_from_string(s) == val);
+
+ p = strjoina("SIG", s);
+ assert_se(signal_from_string(p) == val);
+}
+
+static void test_signal_from_string_number(const char *s, int val) {
+ const char *p;
+
+ assert_se(signal_from_string(s) == val);
+
+ p = strjoina("SIG", s);
+ assert_se(signal_from_string(p) == -EINVAL);
+}
+
+static void test_signal_from_string(void) {
+ char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
+
+ test_signal_to_string_one(SIGHUP);
+ test_signal_to_string_one(SIGTERM);
+ test_signal_to_string_one(SIGRTMIN);
+ test_signal_to_string_one(SIGRTMIN+3);
+ test_signal_to_string_one(SIGRTMAX-4);
+
+ test_signal_from_string_one("RTMIN", SIGRTMIN);
+ test_signal_from_string_one("RTMAX", SIGRTMAX);
+
+ xsprintf(buf, "RTMIN+%d", SIGRTMAX-SIGRTMIN);
+ test_signal_from_string_one(buf, SIGRTMAX);
+
+ xsprintf(buf, "RTMIN+%d", INT_MAX);
+ test_signal_from_string_one(buf, -ERANGE);
+
+ xsprintf(buf, "RTMAX-%d", SIGRTMAX-SIGRTMIN);
+ test_signal_from_string_one(buf, SIGRTMIN);
+
+ xsprintf(buf, "RTMAX-%d", INT_MAX);
+ test_signal_from_string_one(buf, -ERANGE);
+
+ test_signal_from_string_one("", -EINVAL);
+ test_signal_from_string_one("hup", -EINVAL);
+ test_signal_from_string_one("HOGEHOGE", -EINVAL);
+
+ test_signal_from_string_one("RTMIN-5", -EINVAL);
+ test_signal_from_string_one("RTMIN- 5", -EINVAL);
+ test_signal_from_string_one("RTMIN -5", -EINVAL);
+ test_signal_from_string_one("RTMIN+ 5", -EINVAL);
+ test_signal_from_string_one("RTMIN +5", -EINVAL);
+ test_signal_from_string_one("RTMIN+100", -ERANGE);
+ test_signal_from_string_one("RTMIN+-3", -EINVAL);
+ test_signal_from_string_one("RTMIN++3", -EINVAL);
+ test_signal_from_string_one("RTMIN+HUP", -EINVAL);
+ test_signal_from_string_one("RTMIN3", -EINVAL);
+
+ test_signal_from_string_one("RTMAX+5", -EINVAL);
+ test_signal_from_string_one("RTMAX+ 5", -EINVAL);
+ test_signal_from_string_one("RTMAX +5", -EINVAL);
+ test_signal_from_string_one("RTMAX- 5", -EINVAL);
+ test_signal_from_string_one("RTMAX -5", -EINVAL);
+ test_signal_from_string_one("RTMAX-100", -ERANGE);
+ test_signal_from_string_one("RTMAX-+3", -EINVAL);
+ test_signal_from_string_one("RTMAX--3", -EINVAL);
+ test_signal_from_string_one("RTMAX-HUP", -EINVAL);
+
+ test_signal_from_string_number("3", 3);
+ test_signal_from_string_number("+5", 5);
+ test_signal_from_string_number(" +5", 5);
+ test_signal_from_string_number("10000", -ERANGE);
+ test_signal_from_string_number("-2", -ERANGE);
+}
+
static void test_block_signals(void) {
sigset_t ss;
@@ -62,6 +142,8 @@ static void test_ignore_signals(void) {
}
int main(int argc, char *argv[]) {
+ test_rt_signals();
+ test_signal_from_string();
test_block_signals();
test_ignore_signals();
diff --git a/src/test/test-siphash24.c b/src/test/test-siphash24.c
index 7469457be2..218200e480 100644
--- a/src/test/test-siphash24.c
+++ b/src/test/test-siphash24.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "siphash24.h"
#include "util.h"
diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c
index aed6db8423..7a1e496ed2 100644
--- a/src/test/test-sizeof.c
+++ b/src/test/test-sizeof.c
@@ -1,26 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
#include <string.h>
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+
#include "time-util.h"
/* Print information about various types. Useful when diagnosing
@@ -39,7 +24,12 @@ enum Enum {
};
enum BigEnum {
- big_enum_value = UINT64_C(-1),
+ big_enum_value = UINT64_C(1),
+};
+
+enum BigEnum2 {
+ big_enum2_pos = UINT64_C(1),
+ big_enum2_neg = UINT64_C(-1),
};
int main(void) {
@@ -57,6 +47,14 @@ int main(void) {
info(double);
info(long double);
+#ifdef FLT128_MAX
+ info(_Float128);
+ info(_Float64);
+ info(_Float64x);
+ info(_Float32);
+ info(_Float32x);
+#endif
+
info(size_t);
info(ssize_t);
info(time_t);
@@ -68,6 +66,10 @@ int main(void) {
info(enum Enum);
info(enum BigEnum);
+ info(enum BigEnum2);
+ assert_cc(sizeof(enum BigEnum2) == 8);
+ printf("big_enum2_pos → %zu\n", sizeof(big_enum2_pos));
+ printf("big_enum2_neg → %zu\n", sizeof(big_enum2_neg));
return 0;
}
diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c
index 3c2b115fbf..5286442e26 100644
--- a/src/test/test-sleep.c
+++ b/src/test/test-sleep.c
@@ -1,30 +1,49 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include <linux/fiemap.h>
#include <stdio.h>
+#include "fd-util.h"
#include "log.h"
#include "sleep-config.h"
#include "strv.h"
#include "util.h"
+static void test_parse_sleep_config(void) {
+ const char *verb;
+
+ FOREACH_STRING(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")
+ assert_se(parse_sleep_config(verb, NULL, NULL, NULL) == 0);
+}
+
+static int test_fiemap(const char *path) {
+ _cleanup_free_ struct fiemap *fiemap = NULL;
+ _cleanup_close_ int fd = -1;
+ int r;
+
+ fd = open(path, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
+ if (fd < 0)
+ return log_error_errno(errno, "failed to open %s: %m", path);
+ r = read_fiemap(fd, &fiemap);
+ if (r == -EOPNOTSUPP) {
+ log_info("Skipping test, not supported");
+ exit(EXIT_TEST_SKIP);
+ }
+ if (r < 0)
+ return log_error_errno(r, "Unable to read extent map for '%s': %m", path);
+ log_info("extent map information for %s:", path);
+ log_info("\t start: %llu", fiemap->fm_start);
+ log_info("\t length: %llu", fiemap->fm_length);
+ log_info("\t flags: %u", fiemap->fm_flags);
+ log_info("\t number of mapped extents: %u", fiemap->fm_mapped_extents);
+ log_info("\t extent count: %u", fiemap->fm_extent_count);
+ if (fiemap->fm_extent_count > 0)
+ log_info("\t first extent location: %llu",
+ fiemap->fm_extents[0].fe_physical / page_size());
+
+ return 0;
+}
+
static void test_sleep(void) {
_cleanup_strv_free_ char
**standby = strv_new("standby", NULL),
@@ -35,7 +54,9 @@ static void test_sleep(void) {
**platform = strv_new("platform", NULL),
**shutdown = strv_new("shutdown", NULL),
**freez = strv_new("freeze", NULL);
+ int r;
+ log_info("/* configuration */");
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));
@@ -45,19 +66,37 @@ static void test_sleep(void) {
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));
+ log_info("/* running system */");
+ r = can_sleep("suspend");
+ log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ r = can_sleep("hibernate");
+ log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ r = can_sleep("hybrid-sleep");
+ log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ r = can_sleep("suspend-then-hibernate");
+ log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
}
int main(int argc, char* argv[]) {
+ int i, r = 0, k;
+
log_parse_environment();
log_open();
if (getuid() != 0)
log_warning("This program is unlikely to work for unprivileged users");
+ test_parse_sleep_config();
test_sleep();
- return 0;
+ if (argc <= 1)
+ assert_se(test_fiemap(argv[0]) == 0);
+ else
+ for (i = 1; i < argc; i++) {
+ k = test_fiemap(argv[i]);
+ if (r == 0)
+ r = k;
+ }
+
+ return r;
}
diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
index e35a27fa61..ac2ea52a5c 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/types.h>
#include <unistd.h>
@@ -118,6 +100,19 @@ static void test_socket_address_parse_netlink(void) {
assert_se(socket_address_parse_netlink(&a, "route 10") >= 0);
assert_se(a.sockaddr.sa.sa_family == AF_NETLINK);
assert_se(a.protocol == NETLINK_ROUTE);
+
+ /* With spaces and tabs */
+ assert_se(socket_address_parse_netlink(&a, " kobject-uevent ") >= 0);
+ assert_se(socket_address_parse_netlink(&a, " \t kobject-uevent \t 10 \t") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == AF_NETLINK);
+ assert_se(a.protocol == NETLINK_KOBJECT_UEVENT);
+
+ assert_se(socket_address_parse_netlink(&a, "kobject-uevent\t10") >= 0);
+ assert_se(a.sockaddr.sa.sa_family == AF_NETLINK);
+ assert_se(a.protocol == NETLINK_KOBJECT_UEVENT);
+
+ /* oss-fuzz #6884 */
+ assert_se(socket_address_parse_netlink(&a, "\xff") < 0);
}
static void test_socket_address_equal(void) {
diff --git a/src/test/test-specifier.c b/src/test/test-specifier.c
index 6bf312057a..9c7c352b51 100644
--- a/src/test/test-specifier.c
+++ b/src/test/test-specifier.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "log.h"
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
index c606425d2d..43f56a6c20 100644
--- a/src/test/test-stat-util.c
+++ b/src/test/test-stat-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <linux/magic.h>
@@ -61,17 +43,10 @@ static void test_is_symlink(void) {
assert_se(is_symlink(name_link) == 1);
assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
-
unlink(name);
unlink(name_link);
}
-static void test_path_is_os_tree(void) {
- assert_se(path_is_os_tree("/") > 0);
- assert_se(path_is_os_tree("/etc") == 0);
- assert_se(path_is_os_tree("/idontexist") == -ENOENT);
-}
-
static void test_path_is_fs_type(void) {
/* run might not be a mount point in build chroots */
if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0) {
@@ -95,7 +70,6 @@ static void test_path_is_temporary_fs(void) {
int main(int argc, char *argv[]) {
test_files_same();
test_is_symlink();
- test_path_is_os_tree();
test_path_is_fs_type();
test_path_is_temporary_fs();
diff --git a/src/test/test-strbuf.c b/src/test/test-strbuf.c
index 891d7b1d42..9e93bc1751 100644
--- a/src/test/test-strbuf.c
+++ b/src/test/test-strbuf.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdlib.h>
#include <string.h>
@@ -31,9 +13,9 @@ static ssize_t add_string(struct strbuf *sb, const char *s) {
}
static void test_strbuf(void) {
- struct strbuf *sb;
+ _cleanup_(strbuf_cleanupp) struct strbuf *sb;
_cleanup_strv_free_ char **l;
- ssize_t a, b, c, d, e, f, g;
+ ssize_t a, b, c, d, e, f, g, h;
sb = strbuf_new();
@@ -44,6 +26,7 @@ static void test_strbuf(void) {
e = add_string(sb, "aldo"); /* duplicate */
f = add_string(sb, "do"); /* duplicate */
g = add_string(sb, "waldorf"); /* not a duplicate: matches from tail */
+ h = add_string(sb, "");
/* check the content of the buffer directly */
l = strv_parse_nulstr(sb->buf, sb->len);
@@ -53,10 +36,11 @@ static void test_strbuf(void) {
assert_se(streq(l[2], "foo"));
assert_se(streq(l[3], "bar"));
assert_se(streq(l[4], "waldorf"));
+ assert_se(l[5] == NULL);
assert_se(sb->nodes_count == 5); /* root + 4 non-duplicates */
- assert_se(sb->dedup_count == 3);
- assert_se(sb->in_count == 7);
+ assert_se(sb->dedup_count == 4);
+ assert_se(sb->in_count == 8);
assert_se(sb->in_len == 29); /* length of all strings added */
assert_se(sb->dedup_len == 11); /* length of all strings duplicated */
@@ -70,6 +54,7 @@ static void test_strbuf(void) {
assert_se(e == 2);
assert_se(f == 4);
assert_se(g == 15);
+ assert_se(h == 0);
assert_se(streq(sb->buf + a, "waldo"));
assert_se(streq(sb->buf + b, "foo"));
@@ -78,11 +63,10 @@ static void test_strbuf(void) {
assert_se(streq(sb->buf + e, "aldo"));
assert_se(streq(sb->buf + f, "do"));
assert_se(streq(sb->buf + g, "waldorf"));
+ assert_se(streq(sb->buf + h, ""));
strbuf_complete(sb);
assert_se(sb->root == NULL);
-
- strbuf_cleanup(sb);
}
int main(int argc, const char *argv[]) {
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 07ee98465c..3e72ce2c0a 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -1,27 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
+#include "locale-util.h"
#include "macro.h"
#include "string-util.h"
#include "strv.h"
+#include "utf8.h"
static void test_string_erase(void) {
char *x;
@@ -90,6 +74,87 @@ static void test_ascii_strcasecmp_nn(void) {
assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
}
+static void test_cellescape(void) {
+ char buf[40];
+
+ assert_se(streq(cellescape(buf, 1, ""), ""));
+ assert_se(streq(cellescape(buf, 1, "1"), ""));
+ assert_se(streq(cellescape(buf, 1, "12"), ""));
+
+ assert_se(streq(cellescape(buf, 2, ""), ""));
+ assert_se(streq(cellescape(buf, 2, "1"), "1"));
+ assert_se(streq(cellescape(buf, 2, "12"), "."));
+ assert_se(streq(cellescape(buf, 2, "123"), "."));
+
+ assert_se(streq(cellescape(buf, 3, ""), ""));
+ assert_se(streq(cellescape(buf, 3, "1"), "1"));
+ assert_se(streq(cellescape(buf, 3, "12"), "12"));
+ assert_se(streq(cellescape(buf, 3, "123"), ".."));
+ assert_se(streq(cellescape(buf, 3, "1234"), ".."));
+
+ assert_se(streq(cellescape(buf, 4, ""), ""));
+ assert_se(streq(cellescape(buf, 4, "1"), "1"));
+ assert_se(streq(cellescape(buf, 4, "12"), "12"));
+ assert_se(streq(cellescape(buf, 4, "123"), "123"));
+ assert_se(streq(cellescape(buf, 4, "1234"), is_locale_utf8() ? "…" : "..."));
+ assert_se(streq(cellescape(buf, 4, "12345"), is_locale_utf8() ? "…" : "..."));
+
+ assert_se(streq(cellescape(buf, 5, ""), ""));
+ assert_se(streq(cellescape(buf, 5, "1"), "1"));
+ assert_se(streq(cellescape(buf, 5, "12"), "12"));
+ assert_se(streq(cellescape(buf, 5, "123"), "123"));
+ assert_se(streq(cellescape(buf, 5, "1234"), "1234"));
+ assert_se(streq(cellescape(buf, 5, "12345"), is_locale_utf8() ? "1…" : "1..."));
+ assert_se(streq(cellescape(buf, 5, "123456"), is_locale_utf8() ? "1…" : "1..."));
+
+ assert_se(streq(cellescape(buf, 1, "\020"), ""));
+ assert_se(streq(cellescape(buf, 2, "\020"), "."));
+ assert_se(streq(cellescape(buf, 3, "\020"), ".."));
+ assert_se(streq(cellescape(buf, 4, "\020"), "…"));
+ assert_se(streq(cellescape(buf, 5, "\020"), "\\020"));
+
+ assert_se(streq(cellescape(buf, 5, "1234\020"), "1…"));
+ assert_se(streq(cellescape(buf, 6, "1234\020"), "12…"));
+ assert_se(streq(cellescape(buf, 7, "1234\020"), "123…"));
+ assert_se(streq(cellescape(buf, 8, "1234\020"), "1234…"));
+ assert_se(streq(cellescape(buf, 9, "1234\020"), "1234\\020"));
+
+ assert_se(streq(cellescape(buf, 1, "\t\n"), ""));
+ assert_se(streq(cellescape(buf, 2, "\t\n"), "."));
+ assert_se(streq(cellescape(buf, 3, "\t\n"), ".."));
+ assert_se(streq(cellescape(buf, 4, "\t\n"), "…"));
+ assert_se(streq(cellescape(buf, 5, "\t\n"), "\\t\\n"));
+
+ assert_se(streq(cellescape(buf, 5, "1234\t\n"), "1…"));
+ assert_se(streq(cellescape(buf, 6, "1234\t\n"), "12…"));
+ assert_se(streq(cellescape(buf, 7, "1234\t\n"), "123…"));
+ assert_se(streq(cellescape(buf, 8, "1234\t\n"), "1234…"));
+ assert_se(streq(cellescape(buf, 9, "1234\t\n"), "1234\\t\\n"));
+
+ assert_se(streq(cellescape(buf, 4, "x\t\020\n"), "…"));
+ assert_se(streq(cellescape(buf, 5, "x\t\020\n"), "x…"));
+ assert_se(streq(cellescape(buf, 6, "x\t\020\n"), "x…"));
+ assert_se(streq(cellescape(buf, 7, "x\t\020\n"), "x\\t…"));
+ assert_se(streq(cellescape(buf, 8, "x\t\020\n"), "x\\t…"));
+ assert_se(streq(cellescape(buf, 9, "x\t\020\n"), "x\\t…"));
+ assert_se(streq(cellescape(buf, 10, "x\t\020\n"), "x\\t\\020\\n"));
+
+ assert_se(streq(cellescape(buf, 6, "1\011"), "1\\t"));
+ assert_se(streq(cellescape(buf, 6, "1\020"), "1\\020"));
+ assert_se(streq(cellescape(buf, 6, "1\020x"), is_locale_utf8() ? "1…" : "1..."));
+
+ assert_se(streq(cellescape(buf, 40, "1\020"), "1\\020"));
+ assert_se(streq(cellescape(buf, 40, "1\020x"), "1\\020x"));
+
+ assert_se(streq(cellescape(buf, 40, "\a\b\f\n\r\t\v\\\"'"), "\\a\\b\\f\\n\\r\\t\\v\\\\\\\"\\'"));
+ assert_se(streq(cellescape(buf, 6, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a..."));
+ assert_se(streq(cellescape(buf, 7, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a..."));
+ assert_se(streq(cellescape(buf, 8, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a\\b…" : "\\a\\b..."));
+
+ assert_se(streq(cellescape(buf, sizeof buf, "1\020"), "1\\020"));
+ assert_se(streq(cellescape(buf, sizeof buf, "1\020x"), "1\\020x"));
+}
+
static void test_streq_ptr(void) {
assert_se(streq_ptr(NULL, NULL));
assert_se(!streq_ptr("abc", "cdef"));
@@ -148,7 +213,6 @@ static void test_strrep(void) {
assert_se(streq(zero, ""));
}
-
static void test_strappend(void) {
_cleanup_free_ char *t1, *t2, *t3, *t4;
@@ -420,10 +484,23 @@ static void test_strlen_ptr(void) {
assert_se(strlen_ptr(NULL) == 0);
}
+static void test_memory_startswith(void) {
+ assert_se(streq(memory_startswith("", 0, ""), ""));
+ assert_se(streq(memory_startswith("", 1, ""), ""));
+ assert_se(streq(memory_startswith("x", 2, ""), "x"));
+ assert_se(!memory_startswith("", 1, "x"));
+ assert_se(!memory_startswith("", 1, "xxxxxxxx"));
+ assert_se(streq(memory_startswith("xxx", 4, "x"), "xx"));
+ assert_se(streq(memory_startswith("xxx", 4, "xx"), "x"));
+ assert_se(streq(memory_startswith("xxx", 4, "xxx"), ""));
+ assert_se(!memory_startswith("xxx", 4, "xxxx"));
+}
+
int main(int argc, char *argv[]) {
test_string_erase();
test_ascii_strcasecmp_n();
test_ascii_strcasecmp_nn();
+ test_cellescape();
test_streq_ptr();
test_strstrip();
test_strextend();
@@ -447,6 +524,7 @@ int main(int argc, char *argv[]) {
test_split_pair();
test_first_word();
test_strlen_ptr();
+ test_memory_startswith();
return 0;
}
diff --git a/src/test/test-strip-tab-ansi.c b/src/test/test-strip-tab-ansi.c
index 838a6e4db6..362f862221 100644
--- a/src/test/test-strip-tab-ansi.c
+++ b/src/test/test-strip-tab-ansi.c
@@ -1,31 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdio.h>
+#include "alloc-util.h"
#include "string-util.h"
#include "terminal-util.h"
#include "util.h"
int main(int argc, char *argv[]) {
- char *p;
+ _cleanup_free_ char *urlified = NULL, *q = NULL, *qq = NULL;
+ char *p, *z;
assert_se(p = strdup("\tFoobar\tbar\twaldo\t"));
assert_se(strip_tab_ansi(&p, NULL, NULL));
@@ -49,5 +33,24 @@ int main(int argc, char *argv[]) {
assert_se(streq(p, "\x1B[waldo"));
free(p);
+ assert_se(terminal_urlify_path("/etc/fstab", "i am a fabulous link", &urlified) >= 0);
+ assert_se(p = strjoin("something ", urlified, " something-else"));
+ assert_se(q = strdup(p));
+ printf("<%s>\n", p);
+ assert_se(strip_tab_ansi(&p, NULL, NULL));
+ printf("<%s>\n", p);
+ assert_se(streq(p, "something i am a fabulous link something-else"));
+ p = mfree(p);
+
+ /* Truncate the formatted string in the middle of an ANSI sequence (in which case we shouldn't touch the
+ * incomplete sequence) */
+ z = strstr(q, "fstab");
+ if (z) {
+ *z = 0;
+ assert_se(qq = strdup(q));
+ assert_se(strip_tab_ansi(&q, NULL, NULL));
+ assert_se(streq(q, qq));
+ }
+
return 0;
}
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index c6698f4396..1c192239a2 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
@@ -102,7 +83,6 @@ static const char* const input_table_one_empty[] = {
NULL,
};
-
static void test_strv_find(void) {
assert_se(strv_find((char **)input_table_multiple, "three"));
assert_se(!strv_find((char **)input_table_multiple, "four"));
diff --git a/src/test/test-strxcpyx.c b/src/test/test-strxcpyx.c
index 7e2d3c2522..21d56d9be6 100644
--- a/src/test/test-strxcpyx.c
+++ b/src/test/test-strxcpyx.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
diff --git a/src/test/test-systemd-tmpfiles.py b/src/test/test-systemd-tmpfiles.py
index 7e563551cd..13a44f3c4a 100755
--- a/src/test/test-systemd-tmpfiles.py
+++ b/src/test/test-systemd-tmpfiles.py
@@ -1,8 +1,6 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1+
#
-# 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
@@ -67,7 +65,7 @@ def test_invalids(*, user):
test_line('h - - -', user=user)
test_line('H - - -', user=user)
-def test_unitialized_t():
+def test_uninitialized_t():
if os.getuid() == 0:
return
@@ -134,7 +132,7 @@ def test_valid_specifiers(*, user):
if __name__ == '__main__':
test_invalids(user=False)
test_invalids(user=True)
- test_unitialized_t()
+ test_uninitialized_t()
test_valid_specifiers(user=False)
test_valid_specifiers(user=True)
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 023fae040d..944104a25a 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "architecture.h"
#include "automount.h"
@@ -25,6 +7,7 @@
#include "condition.h"
#include "device.h"
#include "execute.h"
+#include "import-util.h"
#include "install.h"
#include "job.h"
#include "journald-server.h"
@@ -33,8 +16,11 @@
#include "locale-util.h"
#include "log.h"
#include "logs-show.h"
+#include "machine-image.h"
#include "mount.h"
#include "path.h"
+#include "process-util.h"
+#include "resolve-util.h"
#include "rlimit-util.h"
#include "scope.h"
#include "service.h"
@@ -52,36 +38,51 @@
int main(int argc, char **argv) {
test_table(architecture, ARCHITECTURE);
+ test_table(assert_type, CONDITION_TYPE);
test_table(automount_result, AUTOMOUNT_RESULT);
test_table(automount_state, AUTOMOUNT_STATE);
+ test_table(cgroup_controller, CGROUP_CONTROLLER);
test_table(cgroup_device_policy, CGROUP_DEVICE_POLICY);
- test_table(condition_type, CONDITION_TYPE);
- test_table(assert_type, CONDITION_TYPE);
+ test_table(cgroup_io_limit_type, CGROUP_IO_LIMIT_TYPE);
+ test_table(collect_mode, COLLECT_MODE);
test_table(condition_result, CONDITION_RESULT);
+ test_table(condition_type, CONDITION_TYPE);
test_table(device_state, DEVICE_STATE);
+ test_table(dnssec_mode, DNSSEC_MODE);
+ test_table(emergency_action, EMERGENCY_ACTION);
+ test_table(exec_directory_type, EXEC_DIRECTORY_TYPE);
test_table(exec_input, EXEC_INPUT);
+ test_table(exec_keyring_mode, EXEC_KEYRING_MODE);
test_table(exec_output, EXEC_OUTPUT);
- test_table(emergency_action, EMERGENCY_ACTION);
+ test_table(exec_preserve_mode, EXEC_PRESERVE_MODE);
+ test_table(exec_utmp_mode, EXEC_UTMP_MODE);
+ test_table(image_type, IMAGE_TYPE);
+ test_table(import_verify, IMPORT_VERIFY);
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(locale_variable, VARIABLE_LC);
test_table(log_target, LOG_TARGET);
test_table(mac_policy, MACPOLICY);
test_table(manager_state, MANAGER_STATE);
+ test_table(manager_timestamp, MANAGER_TIMESTAMP);
test_table(mount_exec_command, MOUNT_EXEC_COMMAND);
test_table(mount_result, MOUNT_RESULT);
test_table(mount_state, MOUNT_STATE);
test_table(name_policy, NAMEPOLICY);
+ test_table(namespace_type, NAMESPACE_TYPE);
test_table(notify_access, NOTIFY_ACCESS);
test_table(output_mode, OUTPUT_MODE);
+ test_table(partition_designator, PARTITION_DESIGNATOR);
test_table(path_result, PATH_RESULT);
test_table(path_state, PATH_STATE);
test_table(path_type, PATH_TYPE);
test_table(protect_home, PROTECT_HOME);
test_table(protect_system, PROTECT_SYSTEM);
+ test_table(resolve_support, RESOLVE_SUPPORT);
test_table(rlimit, RLIMIT);
test_table(scope_result, SCOPE_RESULT);
test_table(scope_state, SCOPE_STATE);
@@ -111,7 +112,6 @@ int main(int argc, char **argv) {
test_table(unit_file_state, UNIT_FILE_STATE);
test_table(unit_load_state, UNIT_LOAD_STATE);
test_table(unit_type, UNIT_TYPE);
- test_table(locale_variable, VARIABLE_LC);
test_table(virtualization, VIRTUALIZATION);
test_table_sparse(object_compressed, OBJECT_COMPRESSED);
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
index 51b3306d16..9f27c74139 100644
--- a/src/test/test-terminal-util.c
+++ b/src/test/test-terminal-util.c
@@ -1,31 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdbool.h>
#include <stdio.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
+#include "strv.h"
#include "terminal-util.h"
#include "util.h"
@@ -76,12 +59,36 @@ static void test_read_one_char(void) {
unlink(name);
}
+static void test_terminal_urlify(void) {
+ _cleanup_free_ char *formatted = NULL;
+
+ assert_se(terminal_urlify("https://www.freedesktop.org/wiki/Software/systemd/", "systemd homepage", &formatted) >= 0);
+ printf("Hey, considere visiting the %s right now! It is very good!\n", formatted);
+
+ formatted = mfree(formatted);
+
+ assert_se(terminal_urlify_path("/etc/fstab", "this link to your /etc/fstab", &formatted) >= 0);
+ printf("Or click on %s to have a look at it!\n", formatted);
+}
+
+static void test_cat_files(void) {
+ assert_se(cat_files("/no/such/file", NULL, 0) == -ENOENT);
+ assert_se(cat_files("/no/such/file", NULL, CAT_FLAGS_MAIN_FILE_OPTIONAL) == 0);
+
+ if (access("/etc/fstab", R_OK) >= 0)
+ assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab"), 0) == 0);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
test_default_term_for_tty();
test_read_one_char();
+ test_terminal_urlify();
+ test_cat_files();
+
+ print_separator();
return 0;
}
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
index ebf85fcc7c..87de8d172c 100644
--- a/src/test/test-time-util.c
+++ b/src/test/test-time-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "random-util.h"
#include "string-util.h"
@@ -26,6 +8,8 @@
static void test_parse_sec(void) {
usec_t u;
+ log_info("/* %s */", __func__);
+
assert_se(parse_sec("5s", &u) >= 0);
assert_se(u == 5 * USEC_PER_SEC);
assert_se(parse_sec("5s500ms", &u) >= 0);
@@ -65,6 +49,8 @@ static void test_parse_sec(void) {
static void test_parse_sec_fix_0(void) {
usec_t u;
+ log_info("/* %s */", __func__);
+
assert_se(parse_sec_fix_0("5s", &u) >= 0);
assert_se(u == 5 * USEC_PER_SEC);
assert_se(parse_sec_fix_0("0s", &u) >= 0);
@@ -78,6 +64,8 @@ static void test_parse_sec_fix_0(void) {
static void test_parse_time(void) {
usec_t u;
+ log_info("/* %s */", __func__);
+
assert_se(parse_time("5", &u, 1) >= 0);
assert_se(u == 5);
@@ -100,6 +88,8 @@ static void test_parse_time(void) {
static void test_parse_nsec(void) {
nsec_t u;
+ log_info("/* %s */", __func__);
+
assert_se(parse_nsec("5s", &u) >= 0);
assert_se(u == 5 * NSEC_PER_SEC);
assert_se(parse_nsec("5s500ms", &u) >= 0);
@@ -133,19 +123,16 @@ static void test_parse_nsec(void) {
}
static void test_format_timespan_one(usec_t x, usec_t accuracy) {
- char *r;
char l[FORMAT_TIMESPAN_MAX];
+ const char *t;
usec_t y;
log_info(USEC_FMT" (at accuracy "USEC_FMT")", x, accuracy);
- r = format_timespan(l, sizeof(l), x, accuracy);
- assert_se(r);
-
- log_info(" = <%s>", l);
-
- assert_se(parse_sec(l, &y) >= 0);
+ assert_se(t = format_timespan(l, sizeof l, x, accuracy));
+ log_info(" = <%s>", t);
+ assert_se(parse_sec(t, &y) >= 0);
log_info(" = "USEC_FMT, y);
if (accuracy <= 0)
@@ -155,6 +142,8 @@ static void test_format_timespan_one(usec_t x, usec_t accuracy) {
}
static void test_format_timespan(usec_t accuracy) {
+ log_info("/* %s accuracy="USEC_FMT" */", __func__, accuracy);
+
test_format_timespan_one(0, accuracy);
test_format_timespan_one(1, accuracy);
test_format_timespan_one(1*USEC_PER_SEC, accuracy);
@@ -181,9 +170,11 @@ static void test_format_timespan(usec_t accuracy) {
}
static void test_timezone_is_valid(void) {
- assert_se(timezone_is_valid("Europe/Berlin"));
- assert_se(timezone_is_valid("Australia/Sydney"));
- assert_se(!timezone_is_valid("Europe/Do not exist"));
+ log_info("/* %s */", __func__);
+
+ assert_se(timezone_is_valid("Europe/Berlin", LOG_ERR));
+ assert_se(timezone_is_valid("Australia/Sydney", LOG_ERR));
+ assert_se(!timezone_is_valid("Europe/Do not exist", LOG_ERR));
}
static void test_get_timezones(void) {
@@ -191,14 +182,18 @@ static void test_get_timezones(void) {
int r;
char **zone;
+ log_info("/* %s */", __func__);
+
r = get_timezones(&zones);
assert_se(r == 0);
STRV_FOREACH(zone, zones)
- assert_se(timezone_is_valid(*zone));
+ assert_se(timezone_is_valid(*zone, LOG_ERR));
}
static void test_usec_add(void) {
+ log_info("/* %s */", __func__);
+
assert_se(usec_add(0, 0) == 0);
assert_se(usec_add(1, 4) == 5);
assert_se(usec_add(USEC_INFINITY, 5) == USEC_INFINITY);
@@ -210,6 +205,8 @@ static void test_usec_add(void) {
}
static void test_usec_sub_unsigned(void) {
+ log_info("/* %s */", __func__);
+
assert_se(usec_sub_unsigned(0, 0) == 0);
assert_se(usec_sub_unsigned(0, 2) == 0);
assert_se(usec_sub_unsigned(0, USEC_INFINITY) == 0);
@@ -231,6 +228,8 @@ static void test_usec_sub_unsigned(void) {
}
static void test_usec_sub_signed(void) {
+ log_info("/* %s */", __func__);
+
assert_se(usec_sub_signed(0, 0) == 0);
assert_se(usec_sub_signed(4, 1) == 3);
assert_se(usec_sub_signed(4, 4) == 0);
@@ -245,6 +244,8 @@ static void test_usec_sub_signed(void) {
static void test_format_timestamp(void) {
unsigned i;
+ log_info("/* %s */", __func__);
+
for (i = 0; i < 100; i++) {
char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)];
usec_t x, y;
@@ -284,27 +285,29 @@ static void test_format_timestamp(void) {
}
}
-static void test_format_timestamp_utc_one(usec_t t, const char *result) {
+static void test_format_timestamp_utc_one(usec_t val, const char *result) {
char buf[FORMAT_TIMESTAMP_MAX];
+ const char *t;
- assert_se(!format_timestamp_utc(buf, sizeof(buf), t) == !result);
-
- if (result)
- assert_se(streq(result, buf));
+ t = format_timestamp_utc(buf, sizeof(buf), val);
+ assert_se(streq_ptr(t, result));
}
static void test_format_timestamp_utc(void) {
+ log_info("/* %s */", __func__);
+
test_format_timestamp_utc_one(0, NULL);
test_format_timestamp_utc_one(1, "Thu 1970-01-01 00:00:00 UTC");
test_format_timestamp_utc_one(USEC_PER_SEC, "Thu 1970-01-01 00:00:01 UTC");
#if SIZEOF_TIME_T == 8
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Thu 9999-12-30 23:59:59 UTC");
+ test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX");
#elif SIZEOF_TIME_T == 4
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Tue 2038-01-19 03:14:07 UTC");
+ test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX");
#endif
- test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX+1, NULL);
test_format_timestamp_utc_one(USEC_INFINITY, NULL);
}
@@ -312,6 +315,8 @@ static void test_dual_timestamp_deserialize(void) {
int r;
dual_timestamp t;
+ log_info("/* %s */", __func__);
+
r = dual_timestamp_deserialize("1234 5678", &t);
assert_se(r == 0);
assert_se(t.realtime == 1234);
@@ -359,6 +364,8 @@ static void assert_similar(usec_t a, usec_t b) {
static void test_usec_shift_clock(void) {
usec_t rt, mn, bt;
+ log_info("/* %s */", __func__);
+
rt = now(CLOCK_REALTIME);
mn = now(CLOCK_MONOTONIC);
bt = now(clock_boottime_or_monotonic());
@@ -384,6 +391,8 @@ static void test_usec_shift_clock(void) {
}
static void test_in_utc_timezone(void) {
+ log_info("/* %s */", __func__);
+
assert_se(setenv("TZ", ":UTC", 1) >= 0);
assert_se(in_utc_timezone());
assert_se(streq(tzname[0], "UTC"));
diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c
index 8e57fe0461..3817790233 100644
--- a/src/test/test-tmpfiles.c
+++ b/src/test/test-tmpfiles.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stdio.h>
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index e765f716ca..bed51c1270 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
- Copyright 2004-2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
***/
#include <errno.h>
@@ -69,10 +53,10 @@ static int fake_filesystems(void) {
}
int main(int argc, char *argv[]) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_udev_event_unref_ struct udev_event *event = NULL;
- _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
- _cleanup_udev_rules_unref_ struct udev_rules *rules = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
+ _cleanup_(udev_event_unrefp) struct udev_event *event = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
+ _cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
char syspath[UTIL_PATH_SIZE];
const char *devpath;
const char *action;
diff --git a/src/test/test-uid-range.c b/src/test/test-uid-range.c
index ce461d606b..65a556c9c6 100644
--- a/src/test/test-uid-range.c
+++ b/src/test/test-uid-range.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stddef.h>
diff --git a/src/test/test-umount.c b/src/test/test-umount.c
new file mode 100644
index 0000000000..770d1a73c8
--- /dev/null
+++ b/src/test/test-umount.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "log.h"
+#include "string-util.h"
+#include "tests.h"
+#include "umount.h"
+#include "util.h"
+
+static void test_mount_points_list(const char *fname) {
+ _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
+ MountPoint *m;
+
+ log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/self/mountinfo");
+
+ LIST_HEAD_INIT(mp_list_head);
+ assert_se(mount_points_list_get(fname, &mp_list_head) >= 0);
+
+ LIST_FOREACH(mount_point, m, mp_list_head)
+ log_debug("path=%s o=%s f=0x%lx try-ro=%s dev=%u:%u",
+ m->path,
+ strempty(m->remount_options),
+ m->remount_flags,
+ yes_no(m->try_remount_ro),
+ major(m->devnum), minor(m->devnum));
+}
+
+static void test_swap_list(const char *fname) {
+ _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
+ MountPoint *m;
+
+ log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/swaps");
+
+ LIST_HEAD_INIT(mp_list_head);
+ assert_se(swap_list_get(fname, &mp_list_head) >= 0);
+
+ LIST_FOREACH(mount_point, m, mp_list_head)
+ log_debug("path=%s o=%s f=0x%lx try-ro=%s dev=%u:%u",
+ m->path,
+ strempty(m->remount_options),
+ m->remount_flags,
+ yes_no(m->try_remount_ro),
+ major(m->devnum), minor(m->devnum));
+}
+
+int main(int argc, char **argv) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_mount_points_list(NULL);
+ test_mount_points_list(get_testdata_dir("/test-umount/empty.mountinfo"));
+ test_mount_points_list(get_testdata_dir("/test-umount/garbled.mountinfo"));
+ test_mount_points_list(get_testdata_dir("/test-umount/rhbug-1554943.mountinfo"));
+
+ test_swap_list(NULL);
+ test_swap_list(get_testdata_dir("/test-umount/example.swaps"));
+}
diff --git a/src/test/test-unaligned.c b/src/test/test-unaligned.c
index 00445fa302..96d6b22be3 100644
--- a/src/test/test-unaligned.c
+++ b/src/test/test-unaligned.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sparse-endian.h"
#include "unaligned.h"
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index 40eeba6af5..09b0179fa1 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stddef.h>
@@ -27,9 +8,12 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "all-units.h"
#include "capability-util.h"
+#include "conf-parser.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "hostname-util.h"
#include "install-printf.h"
@@ -113,8 +97,8 @@ static void test_config_parse_exec(void) {
ExecCommand *c = NULL, *c1;
const char *ccc;
- Manager *m = NULL;
- Unit *u = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(unit_freep) Unit *u = NULL;
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
if (MANAGER_SKIP_TEST(r)) {
@@ -396,7 +380,6 @@ static void test_config_parse_exec(void) {
c1 = c1->command_next;
check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
-
log_info("/* trailing backslash: \\ */");
/* backslash is invalid */
r = config_parse_exec(NULL, "fake", 4, "section", 1,
@@ -441,9 +424,6 @@ static void test_config_parse_exec(void) {
assert_se(c == NULL);
exec_command_free_list(c);
-
- unit_free(u);
- manager_free(m);
}
static void test_config_parse_log_extra_fields(void) {
@@ -461,8 +441,8 @@ static void test_config_parse_log_extra_fields(void) {
int r;
- Manager *m = NULL;
- Unit *u = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(unit_freep) Unit *u = NULL;
ExecContext c = {};
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
@@ -507,9 +487,6 @@ static void test_config_parse_log_extra_fields(void) {
exec_context_free_log_extra_fields(&c);
- unit_free(u);
- manager_free(m);
-
log_info("/* %s – bye */", __func__);
}
@@ -550,7 +527,7 @@ static void test_load_env_file_1(void) {
_cleanup_strv_free_ char **data = NULL;
int r;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
fd = mkostemp_safe(name);
@@ -566,14 +543,13 @@ static void test_load_env_file_1(void) {
assert_se(streq(data[4], "h=h"));
assert_se(streq(data[5], "i=i"));
assert_se(data[6] == NULL);
- unlink(name);
}
static void test_load_env_file_2(void) {
_cleanup_strv_free_ char **data = NULL;
int r;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
fd = mkostemp_safe(name);
@@ -584,14 +560,13 @@ static void test_load_env_file_2(void) {
assert_se(r == 0);
assert_se(streq(data[0], "a=a"));
assert_se(data[1] == NULL);
- unlink(name);
}
static void test_load_env_file_3(void) {
_cleanup_strv_free_ char **data = NULL;
int r;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
fd = mkostemp_safe(name);
@@ -601,12 +576,11 @@ static void test_load_env_file_3(void) {
r = load_env_file(NULL, name, NULL, &data);
assert_se(r == 0);
assert_se(data == NULL);
- unlink(name);
}
static void test_load_env_file_4(void) {
_cleanup_strv_free_ char **data = NULL;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
int r;
@@ -620,14 +594,13 @@ static void test_load_env_file_4(void) {
assert_se(streq(data[1], "MODULE_0=coretemp"));
assert_se(streq(data[2], "MODULE_1=f71882fg"));
assert_se(data[3] == NULL);
- unlink(name);
}
static void test_load_env_file_5(void) {
_cleanup_strv_free_ char **data = NULL;
int r;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
fd = mkostemp_safe(name);
@@ -639,7 +612,6 @@ static void test_load_env_file_5(void) {
assert_se(streq(data[0], "a="));
assert_se(streq(data[1], "b="));
assert_se(data[2] == NULL);
- unlink(name);
}
static void test_install_printf(void) {
@@ -656,8 +628,8 @@ static void test_install_printf(void) {
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((user = uid_to_name(getuid())));
+ assert_se(host = gethostname_malloc());
+ assert_se(user = uid_to_name(getuid()));
assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
#define expect(src, pattern, result) \
@@ -682,6 +654,7 @@ static void test_install_printf(void) {
expect(i, "%N", "name");
expect(i, "%p", "name");
expect(i, "%i", "");
+ expect(i, "%j", "name");
expect(i, "%u", user);
expect(i, "%U", uid);
@@ -766,22 +739,22 @@ static void test_config_parse_capability_set(void) {
static void test_config_parse_rlimit(void) {
struct rlimit * rl[_RLIMIT_MAX] = {};
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
@@ -790,86 +763,86 @@ static void test_config_parse_rlimit(void) {
rl[RLIMIT_NOFILE]->rlim_max = 20;
/* Invalid values don't change rl */
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 416542c83f..2b00ef8cb7 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -1,24 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <pwd.h>
#include <stdio.h>
@@ -26,6 +6,7 @@
#include <string.h>
#include "alloc-util.h"
+#include "all-units.h"
#include "glob-util.h"
#include "hostname-util.h"
#include "macro.h"
@@ -37,6 +18,7 @@
#include "string-util.h"
#include "test-helper.h"
#include "tests.h"
+#include "unit-def.h"
#include "unit-name.h"
#include "unit-printf.h"
#include "unit.h"
@@ -44,29 +26,39 @@
#include "util.h"
static void test_unit_name_is_valid(void) {
- assert_se(unit_name_is_valid("foo.service", UNIT_NAME_ANY));
- assert_se(unit_name_is_valid("foo.service", UNIT_NAME_PLAIN));
+ assert_se( unit_name_is_valid("foo.service", UNIT_NAME_ANY));
+ assert_se( unit_name_is_valid("foo.service", UNIT_NAME_PLAIN));
assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE));
assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_TEMPLATE));
assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE));
- assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_ANY));
+ assert_se( unit_name_is_valid("foo@bar.service", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid("foo@bar.service", UNIT_NAME_PLAIN));
- assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE));
+ assert_se( unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE));
assert_se(!unit_name_is_valid("foo@bar.service", UNIT_NAME_TEMPLATE));
- assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE));
+ assert_se( unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE));
+
+ assert_se( unit_name_is_valid("foo@bar@bar.service", UNIT_NAME_ANY));
+ assert_se(!unit_name_is_valid("foo@bar@bar.service", UNIT_NAME_PLAIN));
+ assert_se( unit_name_is_valid("foo@bar@bar.service", UNIT_NAME_INSTANCE));
+ assert_se(!unit_name_is_valid("foo@bar@bar.service", UNIT_NAME_TEMPLATE));
+ assert_se( unit_name_is_valid("foo@bar@bar.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE));
- assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_ANY));
+ assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_PLAIN));
assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE));
- assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_TEMPLATE));
- assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE));
+ assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_TEMPLATE));
+ assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE));
assert_se(!unit_name_is_valid(".service", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid("", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid("foo.waldo", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid("@.service", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid("@piep.service", UNIT_NAME_ANY));
+
+ assert_se( unit_name_is_valid("user@1000.slice", UNIT_NAME_ANY));
+ assert_se( unit_name_is_valid("user@1000.slice", UNIT_NAME_INSTANCE));
+ assert_se(!unit_name_is_valid("user@1000.slice", UNIT_NAME_TEMPLATE));
}
static void test_unit_name_replace_instance_one(const char *pattern, const char *repl, const char *expected, int ret) {
@@ -99,7 +91,7 @@ static void test_unit_name_from_path_one(const char *path, const char *suffix, c
_cleanup_free_ char *k = NULL;
assert_se(unit_name_to_path(t, &k) == 0);
puts(strna(k));
- assert_se(path_equal(k, isempty(path) ? "/" : path));
+ assert_se(path_equal(k, empty_to_root(path)));
}
}
@@ -127,7 +119,7 @@ static void test_unit_name_from_path_instance_one(const char *pattern, const cha
assert_se(unit_name_to_instance(t, &k) > 0);
assert_se(unit_name_path_unescape(k, &v) == 0);
- assert_se(path_equal(v, isempty(path) ? "/" : path));
+ assert_se(path_equal(v, empty_to_root(path)));
}
}
@@ -162,10 +154,10 @@ static void test_unit_name_to_path(void) {
test_unit_name_to_path_one("home/foo", NULL, -EINVAL);
}
-static void test_unit_name_mangle_one(UnitNameMangle allow_globs, const char *pattern, const char *expect, int ret) {
+static void test_unit_name_mangle_one(bool allow_globs, const char *pattern, const char *expect, int ret) {
_cleanup_free_ char *t = NULL;
- assert_se(unit_name_mangle(pattern, allow_globs, &t) == ret);
+ assert_se(unit_name_mangle(pattern, (allow_globs * UNIT_NAME_MANGLE_GLOB) | UNIT_NAME_MANGLE_WARN, &t) == ret);
puts(strna(t));
assert_se(streq_ptr(t, expect));
@@ -173,37 +165,36 @@ static void test_unit_name_mangle_one(UnitNameMangle allow_globs, const char *pa
_cleanup_free_ char *k = NULL;
assert_se(unit_name_is_valid(t, UNIT_NAME_ANY) ||
- (allow_globs == UNIT_NAME_GLOB && string_is_glob(t)));
+ (allow_globs && string_is_glob(t)));
- assert_se(unit_name_mangle(t, allow_globs, &k) == 0);
+ assert_se(unit_name_mangle(t, (allow_globs * UNIT_NAME_MANGLE_GLOB) | UNIT_NAME_MANGLE_WARN, &k) == 0);
assert_se(streq_ptr(t, k));
}
}
static void test_unit_name_mangle(void) {
puts("-------------------------------------------------");
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "foo.service", "foo.service", 0);
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "/home", "home.mount", 1);
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "/dev/sda", "dev-sda.device", 1);
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
- test_unit_name_mangle_one(UNIT_NAME_NOGLOB, "", NULL, -EINVAL);
-
- test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo.service", "foo.service", 0);
- test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo", "foo.service", 1);
- test_unit_name_mangle_one(UNIT_NAME_GLOB, "foo*", "foo*", 0);
- test_unit_name_mangle_one(UNIT_NAME_GLOB, "ü*", "\\xc3\\xbc*", 1);
+ test_unit_name_mangle_one(false, "foo.service", "foo.service", 0);
+ test_unit_name_mangle_one(false, "/home", "home.mount", 1);
+ test_unit_name_mangle_one(false, "/dev/sda", "dev-sda.device", 1);
+ test_unit_name_mangle_one(false, "üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
+ test_unit_name_mangle_one(false, "foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
+ test_unit_name_mangle_one(false, "_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
+ test_unit_name_mangle_one(false, "_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
+ test_unit_name_mangle_one(false, "xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
+ test_unit_name_mangle_one(false, "", NULL, -EINVAL);
+
+ test_unit_name_mangle_one(true, "foo.service", "foo.service", 0);
+ test_unit_name_mangle_one(true, "foo", "foo.service", 1);
+ test_unit_name_mangle_one(true, "foo*", "foo*", 0);
+ test_unit_name_mangle_one(true, "ü*", "\\xc3\\xbc*", 1);
}
static int test_unit_printf(void) {
- Manager *m = NULL;
- Unit *u, *u2;
- int r;
-
_cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
+ Unit *u;
+ int r;
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
@@ -249,6 +240,9 @@ static int test_unit_printf(void) {
expect(u, "%p", "blah");
expect(u, "%P", "blah");
expect(u, "%i", "");
+ expect(u, "%I", "");
+ expect(u, "%j", "blah");
+ expect(u, "%J", "blah");
expect(u, "%u", user);
expect(u, "%U", uid);
expect(u, "%h", home);
@@ -258,26 +252,41 @@ static int test_unit_printf(void) {
expect(u, "%t", "/run/user/*");
/* templated */
- assert_se(u2 = unit_new(m, sizeof(Service)));
- assert_se(unit_add_name(u2, "blah@foo-foo.service") == 0);
- assert_se(unit_add_name(u2, "blah@foo-foo.service") == 0);
-
- expect(u2, "%n", "blah@foo-foo.service");
- expect(u2, "%N", "blah@foo-foo");
- expect(u2, "%f", "/foo/foo");
- expect(u2, "%p", "blah");
- expect(u2, "%P", "blah");
- expect(u2, "%i", "foo-foo");
- expect(u2, "%I", "foo/foo");
- expect(u2, "%u", user);
- expect(u2, "%U", uid);
- expect(u2, "%h", home);
- expect(u2, "%m", mid);
- expect(u2, "%b", bid);
- expect(u2, "%H", host);
- expect(u2, "%t", "/run/user/*");
-
- manager_free(m);
+ assert_se(u = unit_new(m, sizeof(Service)));
+ assert_se(unit_add_name(u, "blah@foo-foo.service") == 0);
+ assert_se(unit_add_name(u, "blah@foo-foo.service") == 0);
+
+ expect(u, "%n", "blah@foo-foo.service");
+ expect(u, "%N", "blah@foo-foo");
+ expect(u, "%f", "/foo/foo");
+ expect(u, "%p", "blah");
+ expect(u, "%P", "blah");
+ expect(u, "%i", "foo-foo");
+ expect(u, "%I", "foo/foo");
+ expect(u, "%j", "blah");
+ expect(u, "%J", "blah");
+ expect(u, "%u", user);
+ expect(u, "%U", uid);
+ expect(u, "%h", home);
+ expect(u, "%m", mid);
+ expect(u, "%b", bid);
+ expect(u, "%H", host);
+ expect(u, "%t", "/run/user/*");
+
+ /* templated with components */
+ assert_se(u = unit_new(m, sizeof(Slice)));
+ assert_se(unit_add_name(u, "blah-blah\\x2d.slice") == 0);
+
+ expect(u, "%n", "blah-blah\\x2d.slice");
+ expect(u, "%N", "blah-blah\\x2d");
+ expect(u, "%f", "/blah/blah-");
+ expect(u, "%p", "blah-blah\\x2d");
+ expect(u, "%P", "blah/blah-");
+ expect(u, "%i", "");
+ expect(u, "%I", "");
+ expect(u, "%j", "blah\\x2d");
+ expect(u, "%J", "blah-");
+
#undef expect
return 0;
@@ -339,10 +348,10 @@ static void test_unit_name_build(void) {
}
static void test_slice_name_is_valid(void) {
- assert_se(slice_name_is_valid(SPECIAL_ROOT_SLICE));
- assert_se(slice_name_is_valid("foo.slice"));
- assert_se(slice_name_is_valid("foo-bar.slice"));
- assert_se(slice_name_is_valid("foo-bar-baz.slice"));
+ assert_se( slice_name_is_valid(SPECIAL_ROOT_SLICE));
+ assert_se( slice_name_is_valid("foo.slice"));
+ assert_se( slice_name_is_valid("foo-bar.slice"));
+ assert_se( slice_name_is_valid("foo-bar-baz.slice"));
assert_se(!slice_name_is_valid("-foo-bar-baz.slice"));
assert_se(!slice_name_is_valid("foo-bar-baz-.slice"));
assert_se(!slice_name_is_valid("-foo-bar-baz-.slice"));
@@ -351,6 +360,20 @@ static void test_slice_name_is_valid(void) {
assert_se(!slice_name_is_valid(".slice"));
assert_se(!slice_name_is_valid(""));
assert_se(!slice_name_is_valid("foo.service"));
+
+ assert_se(!slice_name_is_valid("foo@.slice"));
+ assert_se(!slice_name_is_valid("foo@bar.slice"));
+ assert_se(!slice_name_is_valid("foo-bar@baz.slice"));
+ assert_se(!slice_name_is_valid("foo@bar@baz.slice"));
+ assert_se(!slice_name_is_valid("foo@bar-baz.slice"));
+ assert_se(!slice_name_is_valid("-foo-bar-baz@.slice"));
+ assert_se(!slice_name_is_valid("foo-bar-baz@-.slice"));
+ assert_se(!slice_name_is_valid("foo-bar-baz@a--b.slice"));
+ assert_se(!slice_name_is_valid("-foo-bar-baz@-.slice"));
+ assert_se(!slice_name_is_valid("foo-bar--baz@.slice"));
+ assert_se(!slice_name_is_valid("foo--bar--baz@.slice"));
+ assert_se(!slice_name_is_valid("@.slice"));
+ assert_se(!slice_name_is_valid("foo@bar.service"));
}
static void test_build_subslice(void) {
@@ -388,6 +411,13 @@ static void test_build_parent_slice(void) {
test_build_parent_slice_one("foo-bar-.slice", NULL, -EINVAL);
test_build_parent_slice_one("foo-bar.service", NULL, -EINVAL);
test_build_parent_slice_one(".slice", NULL, -EINVAL);
+ test_build_parent_slice_one("foo@bar.slice", NULL, -EINVAL);
+ test_build_parent_slice_one("foo-bar@baz.slice", NULL, -EINVAL);
+ test_build_parent_slice_one("foo-bar--@baz.slice", NULL, -EINVAL);
+ test_build_parent_slice_one("-foo-bar@bar.slice", NULL, -EINVAL);
+ test_build_parent_slice_one("foo-bar@-.slice", NULL, -EINVAL);
+ test_build_parent_slice_one("foo@bar.service", NULL, -EINVAL);
+ test_build_parent_slice_one("@.slice", NULL, -EINVAL);
}
static void test_unit_name_to_instance(void) {
@@ -428,7 +458,6 @@ static void test_unit_name_escape(void) {
assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service"));
}
-
static void test_u_n_t_one(const char *name, const char *expected, int ret) {
_cleanup_free_ char *f = NULL;
@@ -465,6 +494,319 @@ static void test_unit_name_path_unescape(void) {
test_unit_name_path_unescape_one("", NULL, -EINVAL);
}
+static void test_unit_name_to_prefix_one(const char *input, int ret, const char *output) {
+ _cleanup_free_ char *k = NULL;
+
+ assert_se(unit_name_to_prefix(input, &k) == ret);
+ assert_se(streq_ptr(k, output));
+}
+
+static void test_unit_name_to_prefix(void) {
+ test_unit_name_to_prefix_one("foobar.service", 0, "foobar");
+ test_unit_name_to_prefix_one("", -EINVAL, NULL);
+ test_unit_name_to_prefix_one("foobar", -EINVAL, NULL);
+ test_unit_name_to_prefix_one(".service", -EINVAL, NULL);
+ test_unit_name_to_prefix_one("quux.quux", -EINVAL, NULL);
+ test_unit_name_to_prefix_one("quux.mount", 0, "quux");
+ test_unit_name_to_prefix_one("quux-quux.mount", 0, "quux-quux");
+ test_unit_name_to_prefix_one("quux@bar.mount", 0, "quux");
+ test_unit_name_to_prefix_one("quux-@.mount", 0, "quux-");
+ test_unit_name_to_prefix_one("@.mount", -EINVAL, NULL);
+}
+
+static void test_unit_name_from_dbus_path_one(const char *input, int ret, const char *output) {
+ _cleanup_free_ char *k = NULL;
+
+ assert_se(unit_name_from_dbus_path(input, &k) == ret);
+ assert_se(streq_ptr(k, output));
+}
+
+static void test_unit_name_from_dbus_path(void) {
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2emount", 0, "-.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2eslice", 0, "-.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/accounts_2ddaemon_2eservice", 0, "accounts-daemon.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/auditd_2eservice", 0, "auditd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/basic_2etarget", 0, "basic.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/bluetooth_2etarget", 0, "bluetooth.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/boot_2eautomount", 0, "boot.automount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/boot_2emount", 0, "boot.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/btrfs_2emount", 0, "btrfs.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/cryptsetup_2dpre_2etarget", 0, "cryptsetup-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/cryptsetup_2etarget", 0, "cryptsetup.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2eservice", 0, "dbus.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dcdrom_2edevice", 0, "dev-cdrom.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M120G2GC_5fCVPO044405HH120QGN_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M120G2GC_CVPO044405HH120QGN.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M120G2GC_5fCVPO044405HH120QGN_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M120G2GC_CVPO044405HH120QGN\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dTSSTcorp_5fCDDVDW_5fTS_5cx2dL633C_5fR6176GLZB14646_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dTSSTcorp_CDDVDW_TS\\x2dL633C_R6176GLZB14646.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x500151795946eab5_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x500151795946eab5.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x500151795946eab5_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x500151795946eab5\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dlabel_2d_5cxe3_5cx82_5cxb7_5cxe3_5cx82_5cxb9_5cxe3_5cx83_5cx86_5cxe3_5cx83_5cxa0_5cxe3_5cx81_5cxa7_5cxe4_5cxba_5cx88_5cxe7_5cxb4_5cx84_5cxe6_5cxb8_5cx88_5cxe3_5cx81_5cxbf_2edevice", 0, "dev-disk-by\\x2dlabel-\\xe3\\x82\\xb7\\xe3\\x82\\xb9\\xe3\\x83\\x86\\xe3\\x83\\xa0\\xe3\\x81\\xa7\\xe4\\xba\\x88\\xe7\\xb4\\x84\\xe6\\xb8\\x88\\xe3\\x81\\xbf.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d59834e50_5cx2d01_2edevice", 0, "dev-disk-by\\x2dpartuuid-59834e50\\x2d01.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d01_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d01.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d02_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d02.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d03_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d03.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d2_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d6_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d6.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d6_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d6\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2d1A34E3F034E3CD37_2edevice", 0, "dev-disk-by\\x2duuid-1A34E3F034E3CD37.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2dB670EBFE70EBC2EB_2edevice", 0, "dev-disk-by\\x2duuid-B670EBFE70EBC2EB.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2dFCD4F509D4F4C6C4_2edevice", 0, "dev-disk-by\\x2duuid-FCD4F509D4F4C6C4.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2db49ead57_5cx2d907c_5cx2d446c_5cx2db405_5cx2d5ca6cd865f5e_2edevice", 0, "dev-disk-by\\x2duuid-b49ead57\\x2d907c\\x2d446c\\x2db405\\x2d5ca6cd865f5e.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dhugepages_2emount", 0, "dev-hugepages.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dmqueue_2emount", 0, "dev-mqueue.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2drfkill_2edevice", 0, "dev-rfkill.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda1_2edevice", 0, "dev-sda1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda2_2edevice", 0, "dev-sda2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda3_2edevice", 0, "dev-sda3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda_2edevice", 0, "dev-sda.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsdb1_2edevice", 0, "dev-sdb1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsdb_2edevice", 0, "dev-sdb.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsr0_2edevice", 0, "dev-sr0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS0_2edevice", 0, "dev-ttyS0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS10_2edevice", 0, "dev-ttyS10.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS11_2edevice", 0, "dev-ttyS11.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS12_2edevice", 0, "dev-ttyS12.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS13_2edevice", 0, "dev-ttyS13.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS14_2edevice", 0, "dev-ttyS14.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS15_2edevice", 0, "dev-ttyS15.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS16_2edevice", 0, "dev-ttyS16.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS17_2edevice", 0, "dev-ttyS17.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS18_2edevice", 0, "dev-ttyS18.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS19_2edevice", 0, "dev-ttyS19.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS1_2edevice", 0, "dev-ttyS1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS20_2edevice", 0, "dev-ttyS20.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS21_2edevice", 0, "dev-ttyS21.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS22_2edevice", 0, "dev-ttyS22.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS23_2edevice", 0, "dev-ttyS23.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS24_2edevice", 0, "dev-ttyS24.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS25_2edevice", 0, "dev-ttyS25.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS26_2edevice", 0, "dev-ttyS26.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS27_2edevice", 0, "dev-ttyS27.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS28_2edevice", 0, "dev-ttyS28.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS29_2edevice", 0, "dev-ttyS29.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS2_2edevice", 0, "dev-ttyS2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS30_2edevice", 0, "dev-ttyS30.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS31_2edevice", 0, "dev-ttyS31.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS3_2edevice", 0, "dev-ttyS3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS4_2edevice", 0, "dev-ttyS4.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS5_2edevice", 0, "dev-ttyS5.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS6_2edevice", 0, "dev-ttyS6.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS7_2edevice", 0, "dev-ttyS7.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS8_2edevice", 0, "dev-ttyS8.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS9_2edevice", 0, "dev-ttyS9.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dcmdline_2eservice", 0, "dracut-cmdline.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dinitqueue_2eservice", 0, "dracut-initqueue.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dmount_2eservice", 0, "dracut-mount.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dmount_2eservice", 0, "dracut-pre-mount.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dpivot_2eservice", 0, "dracut-pre-pivot.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dtrigger_2eservice", 0, "dracut-pre-trigger.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dudev_2eservice", 0, "dracut-pre-udev.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dshutdown_2eservice", 0, "dracut-shutdown.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ebtables_2eservice", 0, "ebtables.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/emergency_2eservice", 0, "emergency.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/emergency_2etarget", 0, "emergency.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/fedora_2dimport_2dstate_2eservice", 0, "fedora-import-state.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/fedora_2dreadonly_2eservice", 0, "fedora-readonly.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/firewalld_2eservice", 0, "firewalld.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_2dpre_2etarget", 0, "getty-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_2etarget", 0, "getty.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_40tty1_2eservice", 0, "getty@tty1.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/graphical_2etarget", 0, "graphical.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/home_2emount", 0, "home.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/init_2escope", 0, "init.scope");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dcleanup_2eservice", 0, "initrd-cleanup.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dfs_2etarget", 0, "initrd-fs.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dparse_2detc_2eservice", 0, "initrd-parse-etc.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2droot_2ddevice_2etarget", 0, "initrd-root-device.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2droot_2dfs_2etarget", 0, "initrd-root-fs.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dswitch_2droot_2eservice", 0, "initrd-switch-root.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dswitch_2droot_2etarget", 0, "initrd-switch-root.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dudevadm_2dcleanup_2ddb_2eservice", 0, "initrd-udevadm-cleanup-db.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2etarget", 0, "initrd.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ip6tables_2eservice", 0, "ip6tables.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ipset_2eservice", 0, "ipset.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/iptables_2eservice", 0, "iptables.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/irqbalance_2eservice", 0, "irqbalance.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/kmod_2dstatic_2dnodes_2eservice", 0, "kmod-static-nodes.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ldconfig_2eservice", 0, "ldconfig.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/lightdm_2eservice", 0, "lightdm.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/livesys_2dlate_2eservice", 0, "livesys-late.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/lm_5fsensors_2eservice", 0, "lm_sensors.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/local_2dfs_2dpre_2etarget", 0, "local-fs-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/local_2dfs_2etarget", 0, "local-fs.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/machines_2etarget", 0, "machines.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/mcelog_2eservice", 0, "mcelog.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/multi_2duser_2etarget", 0, "multi-user.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/network_2dpre_2etarget", 0, "network-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/network_2etarget", 0, "network.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/nss_2dlookup_2etarget", 0, "nss-lookup.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/nss_2duser_2dlookup_2etarget", 0, "nss-user-lookup.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/paths_2etarget", 0, "paths.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dquit_2dwait_2eservice", 0, "plymouth-quit-wait.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dquit_2eservice", 0, "plymouth-quit.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dstart_2eservice", 0, "plymouth-start.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/polkit_2eservice", 0, "polkit.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount", 0, "proc-sys-fs-binfmt_misc.automount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2emount", 0, "proc-sys-fs-binfmt_misc.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rc_2dlocal_2eservice", 0, "rc-local.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dcryptsetup_2etarget", 0, "remote-cryptsetup.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dfs_2dpre_2etarget", 0, "remote-fs-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dfs_2etarget", 0, "remote-fs.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rescue_2eservice", 0, "rescue.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rescue_2etarget", 0, "rescue.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/run_2duser_2d1000_2emount", 0, "run-user-1000.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/session_2d2_2escope", 0, "session-2.scope");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/shutdown_2etarget", 0, "shutdown.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/slices_2etarget", 0, "slices.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/smartd_2eservice", 0, "smartd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sockets_2etarget", 0, "sockets.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sound_2etarget", 0, "sound.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_2etarget", 0, "sshd-keygen.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40ecdsa_2eservice", 0, "sshd-keygen@ecdsa.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40ed25519_2eservice", 0, "sshd-keygen@ed25519.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40rsa_2eservice", 0, "sshd-keygen@rsa.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2eservice", 0, "sshd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/swap_2etarget", 0, "swap.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a02_2e0_2dbacklight_2dacpi_5fvideo0_2edevice", 0, "sys-devices-pci0000:00-0000:00:02.0-backlight-acpi_video0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a02_2e0_2ddrm_2dcard0_2dcard0_5cx2dLVDS_5cx2d1_2dintel_5fbacklight_2edevice", 0, "sys-devices-pci0000:00-0000:00:02.0-drm-card0-card0\\x2dLVDS\\x2d1-intel_backlight.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1a_2e0_2dusb1_2d1_5cx2d1_2d1_5cx2d1_2e6_2d1_5cx2d1_2e6_3a1_2e0_2dbluetooth_2dhci0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1a.0-usb1-1\\x2d1-1\\x2d1.6-1\\x2d1.6:1.0-bluetooth-hci0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1b_2e0_2dsound_2dcard0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1b.0-sound-card0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1c_2e0_2d0000_3a02_3a00_2e0_2dnet_2dwlp2s0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1c.0-0000:02:00.0-net-wlp2s0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1c_2e2_2d0000_3a04_3a00_2e0_2dnet_2denp4s0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1c.2-0000:04:00.0-net-enp4s0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda1_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda2_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda3_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data2_2dhost1_2dtarget1_3a0_3a0_2d1_3a0_3a0_3a0_2dblock_2dsr0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata2-host1-target1:0:0-1:0:0:0-block-sr0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data6_2dhost5_2dtarget5_3a0_3a0_2d5_3a0_3a0_3a0_2dblock_2dsdb_2dsdb1_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata6-host5-target5:0:0-5:0:0:0-block-sdb-sdb1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data6_2dhost5_2dtarget5_3a0_3a0_2d5_3a0_3a0_3a0_2dblock_2dsdb_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata6-host5-target5:0:0-5:0:0:0-block-sdb.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS0_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS10_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS10.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS11_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS11.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS12_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS12.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS13_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS13.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS14_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS14.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS15_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS15.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS16_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS16.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS17_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS17.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS18_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS18.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS19_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS19.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS1_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS20_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS20.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS21_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS21.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS22_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS22.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS23_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS23.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS24_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS24.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS25_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS25.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS26_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS26.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS27_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS27.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS28_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS28.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS29_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS29.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS2_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS30_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS30.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS31_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS31.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS3_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS4_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS4.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS5_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS5.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS6_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS6.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS7_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS7.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS8_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS8.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS9_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS9.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dvirtual_2dmisc_2drfkill_2edevice", 0, "sys-devices-virtual-misc-rfkill.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dfs_2dfuse_2dconnections_2emount", 0, "sys-fs-fuse-connections.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dkernel_2dconfig_2emount", 0, "sys-kernel-config.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dkernel_2ddebug_2emount", 0, "sys-kernel-debug.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dmodule_2dconfigfs_2edevice", 0, "sys-module-configfs.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_2edevice", 0, "sys-subsystem-bluetooth-devices-hci0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2denp4s0_2edevice", 0, "sys-subsystem-net-devices-enp4s0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dwlp2s0_2edevice", 0, "sys-subsystem-net-devices-wlp2s0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sysinit_2etarget", 0, "sysinit.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2eservice", 0, "syslog.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2esocket", 0, "syslog.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2etarget", 0, "syslog.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sysroot_2emount", 0, "sysroot.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dgetty_2eslice", 0, "system-getty.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsshd_5cx2dkeygen_2eslice", 0, "system-sshd\\x2dkeygen.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsystemd_5cx2dbacklight_2eslice", 0, "system-systemd\\x2dbacklight.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsystemd_5cx2dcoredump_2eslice", 0, "system-systemd\\x2dcoredump.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2duser_5cx2druntime_5cx2ddir_2eslice", 0, "system-user\\x2druntime\\x2ddir.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2eslice", 0, "system.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dconsole_2epath", 0, "systemd-ask-password-console.path");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dconsole_2eservice", 0, "systemd-ask-password-console.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dwall_2epath", 0, "systemd-ask-password-wall.path");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dwall_2eservice", 0, "systemd-ask-password-wall.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbacklight_40backlight_3aacpi_5fvideo0_2eservice", 0, "systemd-backlight@backlight:acpi_video0.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbacklight_40backlight_3aintel_5fbacklight_2eservice", 0, "systemd-backlight@backlight:intel_backlight.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbinfmt_2eservice", 0, "systemd-binfmt.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dcoredump_2esocket", 0, "systemd-coredump.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dcoredump_400_2eservice", 0, "systemd-coredump@0.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfirstboot_2eservice", 0, "systemd-firstboot.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfsck_2droot_2eservice", 0, "systemd-fsck-root.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dhwdb_2dupdate_2eservice", 0, "systemd-hwdb-update.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dinitctl_2eservice", 0, "systemd-initctl.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dinitctl_2esocket", 0, "systemd-initctl.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournal_2dcatalog_2dupdate_2eservice", 0, "systemd-journal-catalog-update.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournal_2dflush_2eservice", 0, "systemd-journal-flush.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2daudit_2esocket", 0, "systemd-journald-audit.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2ddev_2dlog_2esocket", 0, "systemd-journald-dev-log.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2eservice", 0, "systemd-journald.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2esocket", 0, "systemd-journald.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dlogind_2eservice", 0, "systemd-logind.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dmachine_2did_2dcommit_2eservice", 0, "systemd-machine-id-commit.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dmodules_2dload_2eservice", 0, "systemd-modules-load.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dnetworkd_2eservice", 0, "systemd-networkd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dnetworkd_2esocket", 0, "systemd-networkd.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drandom_2dseed_2eservice", 0, "systemd-random-seed.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dremount_2dfs_2eservice", 0, "systemd-remount-fs.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dresolved_2eservice", 0, "systemd-resolved.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drfkill_2eservice", 0, "systemd-rfkill.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drfkill_2esocket", 0, "systemd-rfkill.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dsysctl_2eservice", 0, "systemd-sysctl.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dsysusers_2eservice", 0, "systemd-sysusers.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtimesyncd_2eservice", 0, "systemd-timesyncd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2eservice", 0, "systemd-tmpfiles-clean.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer", 0, "systemd-tmpfiles-clean.timer");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dsetup_2ddev_2eservice", 0, "systemd-tmpfiles-setup-dev.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dsetup_2eservice", 0, "systemd-tmpfiles-setup.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudev_2dtrigger_2eservice", 0, "systemd-udev-trigger.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2dcontrol_2esocket", 0, "systemd-udevd-control.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2dkernel_2esocket", 0, "systemd-udevd-kernel.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2eservice", 0, "systemd-udevd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2ddone_2eservice", 0, "systemd-update-done.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2dutmp_2drunlevel_2eservice", 0, "systemd-update-utmp-runlevel.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2dutmp_2eservice", 0, "systemd-update-utmp.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2duser_2dsessions_2eservice", 0, "systemd-user-sessions.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dvconsole_2dsetup_2eservice", 0, "systemd-vconsole-setup.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/time_2dsync_2etarget", 0, "time-sync.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/timers_2etarget", 0, "timers.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/tmp_2emount", 0, "tmp.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/umount_2etarget", 0, "umount.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/unbound_2danchor_2eservice", 0, "unbound-anchor.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/unbound_2danchor_2etimer", 0, "unbound-anchor.timer");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/upower_2eservice", 0, "upower.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2d1000_2eslice", 0, "user-1000.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2druntime_2ddir_401000_2eservice", 0, "user-runtime-dir@1000.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2eslice", 0, "user.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_401000_2eservice", 0, "user@1000.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/usr_2dlocal_2dtexlive_2emount", 0, "usr-local-texlive.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/var_2dlib_2dmachines_2emount", 0, "var-lib-machines.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/wpa_5fsupplicant_2eservice", 0, "wpa_supplicant.service");
+}
+
int main(int argc, char* argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int r, rc = 0;
@@ -498,6 +840,8 @@ int main(int argc, char* argv[]) {
test_unit_name_escape();
test_unit_name_template();
test_unit_name_path_unescape();
+ test_unit_name_to_prefix();
+ test_unit_name_from_dbus_path();
return rc;
}
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index 3a943bf10f..c1428fab02 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "log.h"
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index c04c99dcad..fe3db314a0 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -1,21 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Dave Reisner
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Dave Reisner
***/
#include "alloc-util.h"
@@ -37,11 +22,21 @@ static void test_utf8_is_valid(void) {
}
static void test_ascii_is_valid(void) {
- assert_se(ascii_is_valid("alsdjf\t\vbarr\nba z"));
+ assert_se( ascii_is_valid("alsdjf\t\vbarr\nba z"));
assert_se(!ascii_is_valid("\342\204\242"));
assert_se(!ascii_is_valid("\341\204"));
}
+static void test_ascii_is_valid_n(void) {
+ assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 17));
+ assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 16));
+ assert_se(!ascii_is_valid_n("alsdjf\t\vbarr\nba z", 18));
+ assert_se(!ascii_is_valid_n("\342\204\242", 3));
+ assert_se(!ascii_is_valid_n("\342\204\242", 2));
+ assert_se(!ascii_is_valid_n("\342\204\242", 1));
+ assert_se( ascii_is_valid_n("\342\204\242", 0));
+}
+
static void test_utf8_encoded_valid_unichar(void) {
assert_se(utf8_encoded_valid_unichar("\342\204\242") == 3);
assert_se(utf8_encoded_valid_unichar("\302\256") == 2);
@@ -115,15 +110,26 @@ static void test_utf8_n_codepoints(void) {
assert_se(utf8_n_codepoints("\xF1") == (size_t) -1);
}
+static void test_utf8_console_width(void) {
+ assert_se(utf8_console_width("abc") == 3);
+ assert_se(utf8_console_width("zażółcić gęślą jaźń") == 19);
+ assert_se(utf8_console_width("串") == 2);
+ assert_se(utf8_console_width("") == 0);
+ assert_se(utf8_console_width("…👊🔪💐…") == 8);
+ assert_se(utf8_console_width("\xF1") == (size_t) -1);
+}
+
int main(int argc, char *argv[]) {
test_utf8_is_valid();
test_utf8_is_printable();
test_ascii_is_valid();
+ test_ascii_is_valid_n();
test_utf8_encoded_valid_unichar();
test_utf8_escaping();
test_utf8_escaping_printable();
test_utf16_to_utf8();
test_utf8_n_codepoints();
+ test_utf8_console_width();
return 0;
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 21d90f0888..4d3e5c5b94 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -227,6 +208,10 @@ static void test_raw_clone(void) {
waitpid(pid, &status, __WCLONE);
assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
}
+
+ errno = 0;
+ assert_se(raw_clone(CLONE_FS|CLONE_NEWNS) == -1);
+ assert_se(errno == EINVAL);
}
static void test_physical_memory(void) {
diff --git a/src/test/test-verbs.c b/src/test/test-verbs.c
index 88276a21ea..efb9664b3c 100644
--- a/src/test/test-verbs.c
+++ b/src/test/test-verbs.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 systemd developers
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "macro.h"
#include "strv.h"
diff --git a/src/test/test-watch-pid.c b/src/test/test-watch-pid.c
index ed6c3d05cc..cb43b35bc5 100644
--- a/src/test/test-watch-pid.c
+++ b/src/test/test-watch-pid.c
@@ -3,13 +3,14 @@
#include "log.h"
#include "manager.h"
#include "rm-rf.h"
+#include "service.h"
#include "test-helper.h"
#include "tests.h"
int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+ _cleanup_(manager_freep) Manager *m = NULL;
Unit *a, *b, *c, *u;
- Manager *m;
int r;
log_set_max_level(LOG_DEBUG);
@@ -90,7 +91,5 @@ int main(int argc, char *argv[]) {
unit_unwatch_pid(c, 4711);
assert_se(manager_get_unit_by_pid(m, 4711) == NULL);
- manager_free(m);
-
return 0;
}
diff --git a/src/test/test-watchdog.c b/src/test/test-watchdog.c
index ffcf408f57..2aba3b5a26 100644
--- a/src/test/test-watchdog.c
+++ b/src/test/test-watchdog.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <string.h>
#include <unistd.h>
diff --git a/src/test/test-web-util.c b/src/test/test-web-util.c
index f59a196721..dd1df8c247 100644
--- a/src/test/test-web-util.c
+++ b/src/test/test-web-util.c
@@ -1,29 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "macro.h"
#include "web-util.h"
static void test_is_valid_documentation_url(void) {
assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
- assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
+ assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt")); /* dead */
+ assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst"));
+ assert_se(documentation_url_is_valid("https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html"));
assert_se(documentation_url_is_valid("file:/foo/foo"));
assert_se(documentation_url_is_valid("man:systemd.special(7)"));
assert_se(documentation_url_is_valid("info:bar"));
diff --git a/src/test/test-xattr-util.c b/src/test/test-xattr-util.c
index 36b6480219..72720dccb8 100644
--- a/src/test/test-xattr-util.c
+++ b/src/test/test-xattr-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/test/test-xml.c b/src/test/test-xml.c
index 5b9abc16ba..63e7a10e7b 100644
--- a/src/test/test-xml.c
+++ b/src/test/test-xml.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <stdarg.h>
diff --git a/src/time-wait-sync/time-wait-sync.c b/src/time-wait-sync/time-wait-sync.c
new file mode 100644
index 0000000000..d268fb0c5a
--- /dev/null
+++ b/src/time-wait-sync/time-wait-sync.c
@@ -0,0 +1,265 @@
+/*
+ * systemd service to wait until kernel realtime clock is synchronized
+ *
+ * Copyright © 2018 Peter A. Bigot
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <sys/timerfd.h>
+#include <sys/timex.h>
+#include <unistd.h>
+
+#include "sd-event.h"
+
+#include "fd-util.h"
+#include "fs-util.h"
+#include "missing.h"
+#include "signal-util.h"
+#include "time-util.h"
+
+typedef struct ClockState {
+ int timerfd_fd; /* non-negative is descriptor from timerfd_create */
+ int adjtime_state; /* return value from last adjtimex(2) call */
+ sd_event_source *timerfd_event_source; /* non-null is the active io event source */
+ int inotify_fd;
+ sd_event_source *inotify_event_source;
+ int run_systemd_wd;
+ int run_systemd_timesync_wd;
+ bool has_watchfile;
+} ClockState;
+
+static void clock_state_release_timerfd(ClockState *sp) {
+ sp->timerfd_event_source = sd_event_source_unref(sp->timerfd_event_source);
+ sp->timerfd_fd = safe_close(sp->timerfd_fd);
+}
+
+static void clock_state_release(ClockState *sp) {
+ clock_state_release_timerfd(sp);
+ sp->inotify_event_source = sd_event_source_unref(sp->inotify_event_source);
+ sp->inotify_fd = safe_close(sp->inotify_fd);
+}
+
+static int clock_state_update(ClockState *sp, sd_event *event);
+
+static int update_notify_run_systemd_timesync(ClockState *sp) {
+ sp->run_systemd_timesync_wd = inotify_add_watch(sp->inotify_fd, "/run/systemd/timesync", IN_CREATE|IN_DELETE_SELF);
+ return sp->run_systemd_timesync_wd;
+}
+
+static int timerfd_handler(sd_event_source *s,
+ int fd,
+ uint32_t revents,
+ void *userdata) {
+ ClockState *sp = userdata;
+
+ return clock_state_update(sp, sd_event_source_get_event(s));
+}
+
+static void process_inotify_event(sd_event *event, ClockState *sp, struct inotify_event *e) {
+ if (e->wd == sp->run_systemd_wd) {
+ /* Only thing we care about is seeing if we can start watching /run/systemd/timesync. */
+ if (sp->run_systemd_timesync_wd < 0)
+ update_notify_run_systemd_timesync(sp);
+ } else if (e->wd == sp->run_systemd_timesync_wd) {
+ if (e->mask & IN_DELETE_SELF) {
+ /* Somebody removed /run/systemd/timesync. */
+ (void) inotify_rm_watch(sp->inotify_fd, sp->run_systemd_timesync_wd);
+ sp->run_systemd_timesync_wd = -1;
+ } else
+ /* Somebody might have created /run/systemd/timesync/synchronized. */
+ clock_state_update(sp, event);
+ }
+}
+
+static int inotify_handler(sd_event_source *s,
+ int fd,
+ uint32_t revents,
+ void *userdata) {
+ sd_event *event = sd_event_source_get_event(s);
+ ClockState *sp = userdata;
+ union inotify_event_buffer buffer;
+ struct inotify_event *e;
+ ssize_t l;
+
+ l = read(fd, &buffer, sizeof(buffer));
+ if (l < 0) {
+ if (IN_SET(errno, EAGAIN, EINTR))
+ return 0;
+
+ return log_warning_errno(errno, "Lost access to inotify: %m");
+ }
+ FOREACH_INOTIFY_EVENT(e, buffer, l)
+ process_inotify_event(event, sp, e);
+
+ return 0;
+}
+
+static int clock_state_update(
+ ClockState *sp,
+ sd_event *event) {
+
+ char buf[MAX((size_t)FORMAT_TIMESTAMP_MAX, STRLEN("unrepresentable"))];
+ struct timex tx = {};
+ const char * ts;
+ usec_t t;
+ int r;
+
+ clock_state_release_timerfd(sp);
+
+ /* The kernel supports cancelling timers whenever its realtime clock is "set" (which can happen in a variety of
+ * ways, generally adjustments of at least 500 ms). The way this module works is we set up a timerfd that will
+ * wake when the clock is set, and when that happens we read the clock synchronization state from the return
+ * value of adjtimex(2), which supports the NTP time adjustment protocol.
+ *
+ * The kernel determines whether the clock is synchronized using driver-specific tests, based on time
+ * information passed by an application, generally through adjtimex(2). If the application asserts the clock is
+ * synchronized, but does not also do something that "sets the clock", the timer will not be cancelled and
+ * synchronization will not be detected.
+ *
+ * Similarly, this service will never complete if the application sets the time without also providing
+ * information that adjtimex(2) can use to determine that the clock is synchronized. This generally doesn't
+ * happen, but can if the system has a hardware clock that is accurate enough that the adjustment is too small
+ * to be a "set".
+ *
+ * Both these failure-to-detect situations are covered by having the presence/creation of
+ * /run/systemd/timesync/synchronized, which is considered sufficient to indicate a synchronized clock even if
+ * the kernel has not been updated.
+ *
+ * For timesyncd the initial setting of the time uses settimeofday(2), which sets the clock but does not mark
+ * it synchronized. When an NTP source is selected it sets the clock again with clock_adjtime(2) which marks it
+ * synchronized and also touches /run/systemd/timesync/synchronized which covers the case when the clock wasn't
+ * "set". */
+
+ r = time_change_fd();
+ if (r < 0) {
+ log_error_errno(r, "Failed to create timerfd: %m");
+ goto finish;
+ }
+ sp->timerfd_fd = r;
+
+ r = adjtimex(&tx);
+ if (r < 0) {
+ log_error_errno(errno, "Failed to read adjtimex state: %m");
+ goto finish;
+ }
+ sp->adjtime_state = r;
+
+ if (tx.status & STA_NANO)
+ tx.time.tv_usec /= 1000;
+ t = timeval_load(&tx.time);
+ ts = format_timestamp_us_utc(buf, sizeof(buf), t);
+ if (!ts)
+ strcpy(buf, "unrepresentable");
+ log_info("adjtime state %d status %x time %s", sp->adjtime_state, tx.status, ts);
+
+ sp->has_watchfile = access("/run/systemd/timesync/synchronized", F_OK) >= 0;
+ if (sp->has_watchfile)
+ /* Presence of watch file overrides adjtime_state */
+ r = 0;
+ else if (sp->adjtime_state == TIME_ERROR) {
+ /* Not synchronized. Do a one-shot wait on the descriptor and inform the caller we need to keep
+ * running. */
+ r = sd_event_add_io(event, &sp->timerfd_event_source, sp->timerfd_fd,
+ EPOLLIN, timerfd_handler, sp);
+ if (r < 0) {
+ log_error_errno(r, "Failed to create time change monitor source: %m");
+ goto finish;
+ }
+ r = 1;
+ } else
+ /* Synchronized; we can exit. */
+ r = 0;
+
+ finish:
+ if (r <= 0)
+ (void) sd_event_exit(event, r);
+ return r;
+}
+
+int main(int argc, char * argv[]) {
+ int r;
+ _cleanup_(sd_event_unrefp) sd_event *event;
+ ClockState state = {
+ .timerfd_fd = -1,
+ .inotify_fd = -1,
+ .run_systemd_wd = -1,
+ .run_systemd_timesync_wd = -1,
+ };
+
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+
+ r = sd_event_default(&event);
+ if (r < 0) {
+ log_error_errno(r, "Failed to allocate event loop: %m");
+ goto finish;
+ }
+
+ r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to create sigterm event source: %m");
+ goto finish;
+ }
+
+ r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to create sigint event source: %m");
+ goto finish;
+ }
+
+ r = sd_event_set_watchdog(event, true);
+ if (r < 0) {
+ log_error_errno(r, "Failed to create watchdog event source: %m");
+ goto finish;
+ }
+
+ r = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
+ if (r < 0) {
+ log_error_errno(errno, "Failed to create inotify descriptor: %m");
+ goto finish;
+ }
+ state.inotify_fd = r;
+
+ r = sd_event_add_io(event, &state.inotify_event_source, state.inotify_fd,
+ EPOLLIN, inotify_handler, &state);
+ if (r < 0) {
+ log_error_errno(r, "Failed to create notify event source: %m");
+ goto finish;
+ }
+
+ r = inotify_add_watch(state.inotify_fd, "/run/systemd/", IN_CREATE);
+ if (r < 0) {
+ log_error_errno(errno, "Failed to watch /run/systemd/: %m");
+ goto finish;
+ }
+ state.run_systemd_wd = r;
+
+ (void) update_notify_run_systemd_timesync(&state);
+
+ r = clock_state_update(&state, event);
+ if (r > 0) {
+ r = sd_event_loop(event);
+ if (r < 0)
+ log_error_errno(r, "Failed in event loop: %m");
+ }
+
+ if (state.has_watchfile)
+ log_debug("Exit enabled by: /run/systemd/timesync/synchonized");
+
+ if (state.adjtime_state == TIME_ERROR)
+ log_info("Exit without adjtimex synchronized.");
+
+ finish:
+ clock_state_release(&state);
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/timedate/meson.build b/src/timedate/meson.build
index 87482c04e5..46c7360da3 100644
--- a/src/timedate/meson.build
+++ b/src/timedate/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
if conf.get('ENABLE_TIMEDATED') == 1
install_data('org.freedesktop.timedate1.conf',
diff --git a/src/timedate/org.freedesktop.timedate1.policy b/src/timedate/org.freedesktop.timedate1.policy
index d488572ae3..b6303ba1dd 100644
--- a/src/timedate/org.freedesktop.timedate1.policy
+++ b/src/timedate/org.freedesktop.timedate1.policy
@@ -41,8 +41,7 @@
<action id="org.freedesktop.timedate1.set-local-rtc">
<description gettext-domain="systemd">Set RTC to local timezone or UTC</description>
- <message gettext-domain="systemd">Authentication is required to control whether
- the RTC stores the local or UTC time.</message>
+ <message gettext-domain="systemd">Authentication is required to control whether the RTC stores the local or UTC time.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -52,8 +51,7 @@
<action id="org.freedesktop.timedate1.set-ntp">
<description gettext-domain="systemd">Turn network time synchronization on or off</description>
- <message gettext-domain="systemd">Authentication is required to control whether
- network time synchronization shall be enabled.</message>
+ <message gettext-domain="systemd">Authentication is required to control whether network time synchronization shall be enabled.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index d0a510468e..befc8cb723 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -1,26 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 <getopt.h>
#include <locale.h>
+#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -28,46 +10,47 @@
#include "bus-error.h"
#include "bus-util.h"
+#include "in-addr-util.h"
#include "pager.h"
#include "parse-util.h"
#include "spawn-polkit-agent.h"
+#include "sparse-endian.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "util.h"
+#include "verbs.h"
static bool arg_no_pager = false;
static bool arg_ask_password = true;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static char *arg_host = NULL;
static bool arg_adjust_system_clock = false;
+static bool arg_monitor = false;
+static char **arg_property = NULL;
+static bool arg_value = false;
+static bool arg_all = false;
typedef struct StatusInfo {
usec_t time;
- char *timezone;
+ const char *timezone;
usec_t rtc_time;
- int rtc_local;
+ bool rtc_local;
- int ntp_enabled;
- int ntp_capable;
- int ntp_synced;
+ bool ntp_capable;
+ bool ntp_active;
+ bool ntp_synced;
} StatusInfo;
-static void status_info_clear(StatusInfo *info) {
- if (info) {
- free(info->timezone);
- zero(*info);
- }
-}
-
static void print_status_info(const StatusInfo *i) {
+ const char *old_tz = NULL, *tz;
+ bool have_time = false;
char a[LINE_MAX];
struct tm tm;
time_t sec;
- bool have_time = false;
- const char *old_tz = NULL, *tz;
- int r;
size_t n;
+ int r;
assert(i);
@@ -93,13 +76,13 @@ static void print_status_info(const StatusInfo *i) {
if (have_time) {
n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
- printf(" Local time: %s\n", n > 0 ? a : "n/a");
+ printf(" Local time: %s\n", n > 0 ? a : "n/a");
n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
- printf(" Universal time: %s\n", n > 0 ? a : "n/a");
+ printf(" Universal time: %s\n", n > 0 ? a : "n/a");
} else {
- printf(" Local time: %s\n", "n/a");
- printf(" Universal time: %s\n", "n/a");
+ printf(" Local time: %s\n", "n/a");
+ printf(" Universal time: %s\n", "n/a");
}
if (i->rtc_time > 0) {
@@ -107,9 +90,9 @@ static void print_status_info(const StatusInfo *i) {
rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC);
n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
- printf(" RTC time: %s\n", n > 0 ? a : "n/a");
+ printf(" RTC time: %s\n", n > 0 ? a : "n/a");
} else
- printf(" RTC time: %s\n", "n/a");
+ printf(" RTC time: %s\n", "n/a");
if (have_time)
n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm));
@@ -124,13 +107,13 @@ static void print_status_info(const StatusInfo *i) {
else
tzset();
- printf(" Time zone: %s (%s)\n"
- " System clock synchronized: %s\n"
- "systemd-timesyncd.service active: %s\n"
- " RTC in local TZ: %s\n",
+ printf(" Time zone: %s (%s)\n"
+ "System clock synchronized: %s\n"
+ " NTP service: %s\n"
+ " RTC in local TZ: %s\n",
strna(i->timezone), have_time && n > 0 ? a : "n/a",
yes_no(i->ntp_synced),
- i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
+ i->ntp_capable ? (i->ntp_active ? "active" : "inactive") : "n/a",
yes_no(i->rtc_local));
if (i->rtc_local)
@@ -143,20 +126,22 @@ static void print_status_info(const StatusInfo *i) {
" 'timedatectl set-local-rtc 0'.%s\n", ansi_highlight(), ansi_normal());
}
-static int show_status(sd_bus *bus, char **args, unsigned n) {
- _cleanup_(status_info_clear) StatusInfo info = {};
+static int show_status(int argc, char **argv, void *userdata) {
+ StatusInfo info = {};
static const struct bus_properties_map map[] = {
- { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) },
- { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) },
- { "NTP", "b", NULL, offsetof(StatusInfo, ntp_enabled) },
+ { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) },
+ { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) },
+ { "NTP", "b", NULL, offsetof(StatusInfo, ntp_active) },
{ "CanNTP", "b", NULL, offsetof(StatusInfo, ntp_capable) },
- { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) },
- { "TimeUSec", "t", NULL, offsetof(StatusInfo, time) },
- { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) },
+ { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) },
+ { "TimeUSec", "t", NULL, offsetof(StatusInfo, time) },
+ { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) },
{}
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ sd_bus *bus = userdata;
int r;
assert(bus);
@@ -165,7 +150,9 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
"org.freedesktop.timedate1",
"/org/freedesktop/timedate1",
map,
+ BUS_MAP_BOOLEAN_AS_BOOL,
&error,
+ &m,
&info);
if (r < 0)
return log_error_errno(r, "Failed to query server: %s", bus_error_message(&error, r));
@@ -175,22 +162,38 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int set_time(sd_bus *bus, char **args, unsigned n) {
+static int show_properties(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
+ int r;
+
+ assert(bus);
+
+ r = bus_print_all_properties(bus,
+ "org.freedesktop.timedate1",
+ "/org/freedesktop/timedate1",
+ NULL,
+ arg_property,
+ arg_value,
+ arg_all,
+ NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 0;
+}
+
+static int set_time(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool relative = false, interactive = arg_ask_password;
+ sd_bus *bus = userdata;
usec_t t;
int r;
- assert(args);
- assert(n == 2);
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- r = parse_timestamp(args[1], &t);
- if (r < 0) {
- log_error("Failed to parse time specification: %s", args[1]);
- return r;
- }
+ r = parse_timestamp(argv[1], &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse time specification '%s': %m", argv[1]);
r = sd_bus_call_method(bus,
"org.freedesktop.timedate1",
@@ -199,20 +202,18 @@ static int set_time(sd_bus *bus, char **args, unsigned n) {
"SetTime",
&error,
NULL,
- "xbb", (int64_t)t, relative, interactive);
+ "xbb", (int64_t) t, relative, interactive);
if (r < 0)
- log_error("Failed to set time: %s", bus_error_message(&error, -r));
+ log_error("Failed to set time: %s", bus_error_message(&error, r));
return r;
}
-static int set_timezone(sd_bus *bus, char **args, unsigned n) {
+static int set_timezone(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
- assert(args);
- assert(n == 2);
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
r = sd_bus_call_method(bus,
@@ -222,27 +223,23 @@ static int set_timezone(sd_bus *bus, char **args, unsigned n) {
"SetTimezone",
&error,
NULL,
- "sb", args[1], arg_ask_password);
+ "sb", argv[1], arg_ask_password);
if (r < 0)
- log_error("Failed to set time zone: %s", bus_error_message(&error, -r));
+ log_error("Failed to set time zone: %s", bus_error_message(&error, r));
return r;
}
-static int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
+static int set_local_rtc(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r, b;
- assert(args);
- assert(n == 2);
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- b = parse_boolean(args[1]);
- if (b < 0) {
- log_error("Failed to parse local RTC setting: %s", args[1]);
- return b;
- }
+ b = parse_boolean(argv[1]);
+ if (b < 0)
+ return log_error_errno(b, "Failed to parse local RTC setting '%s': %m", argv[1]);
r = sd_bus_call_method(bus,
"org.freedesktop.timedate1",
@@ -253,25 +250,21 @@ static int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
NULL,
"bbb", b, arg_adjust_system_clock, arg_ask_password);
if (r < 0)
- log_error("Failed to set local RTC: %s", bus_error_message(&error, -r));
+ log_error("Failed to set local RTC: %s", bus_error_message(&error, r));
return r;
}
-static int set_ntp(sd_bus *bus, char **args, unsigned n) {
+static int set_ntp(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int b, r;
- assert(args);
- assert(n == 2);
-
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- b = parse_boolean(args[1]);
- if (b < 0) {
- log_error("Failed to parse NTP setting: %s", args[1]);
- return b;
- }
+ b = parse_boolean(argv[1]);
+ if (b < 0)
+ return log_error_errno(b, "Failed to parse NTP setting '%s': %m", argv[1]);
r = sd_bus_call_method(bus,
"org.freedesktop.timedate1",
@@ -282,29 +275,425 @@ static int set_ntp(sd_bus *bus, char **args, unsigned n) {
NULL,
"bb", b, arg_ask_password);
if (r < 0)
- log_error("Failed to set ntp: %s", bus_error_message(&error, -r));
+ log_error("Failed to set ntp: %s", bus_error_message(&error, r));
return r;
}
-static int list_timezones(sd_bus *bus, char **args, unsigned n) {
+static int list_timezones(int argc, char **argv, void *userdata) {
_cleanup_strv_free_ char **zones = NULL;
int r;
- assert(args);
- assert(n == 1);
-
r = get_timezones(&zones);
if (r < 0)
return log_error_errno(r, "Failed to read list of time zones: %m");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
strv_print(zones);
return 0;
}
-static void help(void) {
+typedef struct NTPStatusInfo {
+ const char *server_name;
+ char *server_address;
+ usec_t poll_interval, poll_max, poll_min;
+ usec_t root_distance_max;
+
+ uint32_t leap, version, mode, stratum;
+ int32_t precision;
+ usec_t root_delay, root_dispersion;
+ union {
+ char str[5];
+ uint32_t val;
+ } reference;
+ usec_t origin, recv, trans, dest;
+
+ bool spike;
+ uint64_t packet_count;
+ usec_t jitter;
+
+ int64_t freq;
+} NTPStatusInfo;
+
+static void ntp_status_info_clear(NTPStatusInfo *p) {
+ p->server_address = mfree(p->server_address);
+}
+
+static const char * const ntp_leap_table[4] = {
+ [0] = "normal",
+ [1] = "last minute of the day has 61 seconds",
+ [2] = "last minute of the day has 59 seconds",
+ [3] = "not synchronized",
+};
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ntp_leap, uint32_t);
+#pragma GCC diagnostic pop
+
+static void print_ntp_status_info(NTPStatusInfo *i) {
+ char ts[FORMAT_TIMESPAN_MAX], tmin[FORMAT_TIMESPAN_MAX], tmax[FORMAT_TIMESPAN_MAX];
+ usec_t delay, t14, t23, offset, root_distance;
+ bool offset_sign;
+
+ assert(i);
+
+ /*
+ * "Timestamp Name ID When Generated
+ * ------------------------------------------------------------
+ * Originate Timestamp T1 time request sent by client
+ * Receive Timestamp T2 time request received by server
+ * Transmit Timestamp T3 time reply sent by server
+ * Destination Timestamp T4 time reply received by client
+ *
+ * The round-trip delay, d, and system clock offset, t, are defined as:
+ * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2"
+ */
+
+ printf(" Server: %s (%s)\n",
+ i->server_address, i->server_name);
+ printf("Poll interval: %s (min: %s; max %s)\n",
+ format_timespan(ts, sizeof(ts), i->poll_interval, 0),
+ format_timespan(tmin, sizeof(tmin), i->poll_min, 0),
+ format_timespan(tmax, sizeof(tmax), i->poll_max, 0));
+
+ if (i->packet_count == 0) {
+ printf(" Packet count: 0\n");
+ return;
+ }
+
+ if (i->dest < i->origin || i->trans < i->recv || i->dest - i->origin < i->trans - i->recv) {
+ log_error("Invalid NTP response");
+ return;
+ }
+
+ delay = (i->dest - i->origin) - (i->trans - i->recv);
+
+ t14 = i->origin + i->dest;
+ t23 = i->recv + i->trans;
+ offset_sign = t14 < t23;
+ offset = (offset_sign ? t23 - t14 : t14 - t23) / 2;
+
+ root_distance = i->root_delay / 2 + i->root_dispersion;
+
+ printf(" Leap: %s\n"
+ " Version: %" PRIu32 "\n"
+ " Stratum: %" PRIu32 "\n",
+ ntp_leap_to_string(i->leap),
+ i->version,
+ i->stratum);
+ if (i->stratum <= 1)
+ printf(" Reference: %s\n", i->reference.str);
+ else
+ printf(" Reference: %" PRIX32 "\n", be32toh(i->reference.val));
+ printf(" Precision: %s (%" PRIi32 ")\n",
+ format_timespan(ts, sizeof(ts), DIV_ROUND_UP((nsec_t) (exp2(i->precision) * NSEC_PER_SEC), NSEC_PER_USEC), 0),
+ i->precision);
+ printf("Root distance: %s (max: %s)\n",
+ format_timespan(ts, sizeof(ts), root_distance, 0),
+ format_timespan(tmax, sizeof(tmax), i->root_distance_max, 0));
+ printf(" Offset: %s%s\n",
+ offset_sign ? "+" : "-",
+ format_timespan(ts, sizeof(ts), offset, 0));
+ printf(" Delay: %s\n",
+ format_timespan(ts, sizeof(ts), delay, 0));
+ printf(" Jitter: %s\n",
+ format_timespan(ts, sizeof(ts), i->jitter, 0));
+ printf(" Packet count: %" PRIu64 "\n", i->packet_count);
+
+ if (!i->spike)
+ printf(" Frequency: %+.3fppm\n",
+ (double) i->freq / 0x10000);
+}
+
+static int map_server_address(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ char **p = (char **) userdata;
+ const void *d;
+ int family, r;
+ size_t sz;
+
+ assert(p);
+
+ r = sd_bus_message_enter_container(m, 'r', "iay");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(m, "i", &family);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read_array(m, 'y', &d, &sz);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ if (sz == 0 && family == AF_UNSPEC) {
+ *p = mfree(*p);
+ return 0;
+ }
+
+ if (!IN_SET(family, AF_INET, AF_INET6)) {
+ log_error("Unknown address family %i", family);
+ return -EINVAL;
+ }
+
+ if (sz != FAMILY_ADDRESS_SIZE(family)) {
+ log_error("Invalid address size");
+ return -EINVAL;
+ }
+
+ r = in_addr_to_string(family, d, p);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int map_ntp_message(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+ NTPStatusInfo *p = userdata;
+ const void *d;
+ size_t sz;
+ int32_t b;
+ int r;
+
+ assert(p);
+
+ r = sd_bus_message_enter_container(m, 'r', "uuuuittayttttbtt");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(m, "uuuuitt",
+ &p->leap, &p->version, &p->mode, &p->stratum, &p->precision,
+ &p->root_delay, &p->root_dispersion);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read_array(m, 'y', &d, &sz);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(m, "ttttbtt",
+ &p->origin, &p->recv, &p->trans, &p->dest,
+ &b, &p->packet_count, &p->jitter);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ if (sz != 4)
+ return -EINVAL;
+
+ memcpy(p->reference.str, d, sz);
+
+ p->spike = b;
+
+ return 0;
+}
+
+static int show_timesync_status_once(sd_bus *bus) {
+ static const struct bus_properties_map map_timesync[] = {
+ { "ServerName", "s", NULL, offsetof(NTPStatusInfo, server_name) },
+ { "ServerAddress", "(iay)", map_server_address, offsetof(NTPStatusInfo, server_address) },
+ { "PollIntervalUSec", "t", NULL, offsetof(NTPStatusInfo, poll_interval) },
+ { "PollIntervalMinUSec", "t", NULL, offsetof(NTPStatusInfo, poll_min) },
+ { "PollIntervalMaxUSec", "t", NULL, offsetof(NTPStatusInfo, poll_max) },
+ { "RootDistanceMaxUSec", "t", NULL, offsetof(NTPStatusInfo, root_distance_max) },
+ { "NTPMessage", "(uuuuittayttttbtt)", map_ntp_message, 0 },
+ { "Frequency", "x", NULL, offsetof(NTPStatusInfo, freq) },
+ {}
+ };
+ _cleanup_(ntp_status_info_clear) NTPStatusInfo info = {};
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ int r;
+
+ assert(bus);
+
+ r = bus_map_all_properties(bus,
+ "org.freedesktop.timesync1",
+ "/org/freedesktop/timesync1",
+ map_timesync,
+ BUS_MAP_BOOLEAN_AS_BOOL,
+ &error,
+ &m,
+ &info);
+ if (r < 0)
+ return log_error_errno(r, "Failed to query server: %s", bus_error_message(&error, r));
+
+ if (arg_monitor && !terminal_is_dumb())
+ fputs(ANSI_HOME_CLEAR, stdout);
+
+ print_ntp_status_info(&info);
+
+ return 0;
+}
+
+static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ const char *name;
+ int r;
+
+ assert(m);
+
+ r = sd_bus_message_read(m, "s", &name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read interface name: %m");
+
+ if (!streq_ptr(name, "org.freedesktop.timesync1.Manager"))
+ return 0;
+
+ return show_timesync_status_once(sd_bus_message_get_bus(m));
+}
+
+static int show_timesync_status(int argc, char **argv, void *userdata) {
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+ sd_bus *bus = userdata;
+ int r;
+
+ assert(bus);
+
+ r = show_timesync_status_once(bus);
+ if (r < 0)
+ return r;
+
+ if (!arg_monitor)
+ return 0;
+
+ r = sd_event_default(&event);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get event loop: %m");
+
+ r = sd_bus_match_signal(bus,
+ NULL,
+ "org.freedesktop.timesync1",
+ "/org/freedesktop/timesync1",
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ on_properties_changed, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to request match for PropertiesChanged signal: %m");
+
+ r = sd_bus_attach_event(bus, event, SD_EVENT_PRIORITY_NORMAL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach bus to event loop: %m");
+
+ r = sd_event_loop(event);
+ if (r < 0)
+ return log_error_errno(r, "Failed to run event loop: %m");
+
+ return 0;
+}
+
+#define property(name, fmt, ...) \
+ do { \
+ if (value) \
+ printf(fmt "\n", __VA_ARGS__); \
+ else \
+ printf("%s=" fmt "\n", name, __VA_ARGS__); \
+ } while (0)
+
+static int print_timesync_property(const char *name, sd_bus_message *m, bool value, bool all) {
+ char type;
+ const char *contents;
+ int r;
+
+ assert(name);
+ assert(m);
+
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
+
+ switch (type) {
+
+ case SD_BUS_TYPE_STRUCT:
+ if (streq(name, "NTPMessage")) {
+ _cleanup_(ntp_status_info_clear) NTPStatusInfo i = {};
+ char ts[FORMAT_TIMESPAN_MAX], stamp[FORMAT_TIMESTAMP_MAX];
+
+ r = map_ntp_message(NULL, NULL, m, NULL, &i);
+ if (r < 0)
+ return r;
+
+ if (i.packet_count == 0)
+ return 1;
+
+ if (!value) {
+ fputs(name, stdout);
+ fputc('=', stdout);
+ }
+
+ printf("{ Leap=%u, Version=%u, Mode=%u, Stratum=%u, Precision=%i,",
+ i.leap, i.version, i.mode, i.stratum, i.precision);
+ printf(" RootDelay=%s,",
+ format_timespan(ts, sizeof(ts), i.root_delay, 0));
+ printf(" RootDispersion=%s,",
+ format_timespan(ts, sizeof(ts), i.root_dispersion, 0));
+
+ if (i.stratum == 1)
+ printf(" Reference=%s,", i.reference.str);
+ else
+ printf(" Reference=%" PRIX32 ",", be32toh(i.reference.val));
+
+ printf(" OriginateTimestamp=%s,",
+ format_timestamp(stamp, sizeof(stamp), i.origin));
+ printf(" ReceiveTimestamp=%s,",
+ format_timestamp(stamp, sizeof(stamp), i.recv));
+ printf(" TransmitTimestamp=%s,",
+ format_timestamp(stamp, sizeof(stamp), i.trans));
+ printf(" DestinationTimestamp=%s,",
+ format_timestamp(stamp, sizeof(stamp), i.dest));
+ printf(" Ignored=%s PacketCount=%" PRIu64 ",",
+ yes_no(i.spike), i.packet_count);
+ printf(" Jitter=%s }\n",
+ format_timespan(ts, sizeof(ts), i.jitter, 0));
+
+ return 1;
+
+ } else if (streq(name, "ServerAddress")) {
+ _cleanup_free_ char *str = NULL;
+
+ r = map_server_address(NULL, NULL, m, NULL, &str);
+ if (r < 0)
+ return r;
+
+ if (arg_all || !isempty(str))
+ property(name, "%s", str);
+
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int show_timesync(int argc, char **argv, void *userdata) {
+ sd_bus *bus = userdata;
+ int r;
+
+ assert(bus);
+
+ r = bus_print_all_properties(bus,
+ "org.freedesktop.timesync1",
+ "/org/freedesktop/timesync1",
+ print_timesync_property,
+ arg_property,
+ arg_value,
+ arg_all,
+ NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ return 0;
+}
+
+static int help(void) {
printf("%s [OPTIONS...] COMMAND ...\n\n"
"Query or change system time and date settings.\n\n"
" -h --help Show this help message\n"
@@ -313,15 +702,31 @@ static void help(void) {
" --no-ask-password Do not prompt for password\n"
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
- " --adjust-system-clock Adjust system clock when changing local RTC mode\n\n"
+ " --adjust-system-clock Adjust system clock when changing local RTC mode\n"
+ " --monitor Monitor status of systemd-timesyncd\n"
+ " -p --property=NAME Show only properties by this name\n"
+ " -a --all Show all properties, including empty ones\n"
+ " --value When showing properties, only print the value\n"
+ "\n"
"Commands:\n"
" status Show current time settings\n"
+ " show Show properties of systemd-timedated\n"
" set-time TIME Set system time\n"
" set-timezone ZONE Set system time zone\n"
" list-timezones Show known time zones\n"
" set-local-rtc BOOL Control whether RTC is in local time\n"
- " set-ntp BOOL Enable or disable network time synchronization\n",
- program_invocation_short_name);
+ " set-ntp BOOL Enable or disable network time synchronization\n"
+ "\n"
+ "systemd-timesyncd Commands:\n"
+ " timesync-status Show status of systemd-timesyncd\n"
+ " show-timesync Show properties of systemd-timesyncd\n"
+ , program_invocation_short_name);
+
+ return 0;
+}
+
+static int verb_help(int argc, char **argv, void *userdata) {
+ return help();
}
static int parse_argv(int argc, char *argv[]) {
@@ -330,7 +735,9 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_ADJUST_SYSTEM_CLOCK,
- ARG_NO_ASK_PASSWORD
+ ARG_NO_ASK_PASSWORD,
+ ARG_MONITOR,
+ ARG_VALUE,
};
static const struct option options[] = {
@@ -341,21 +748,24 @@ static int parse_argv(int argc, char *argv[]) {
{ "machine", required_argument, NULL, 'M' },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{ "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK },
+ { "monitor", no_argument, NULL, ARG_MONITOR },
+ { "property", required_argument, NULL, 'p' },
+ { "all", no_argument, NULL, 'a' },
+ { "value", no_argument, NULL, ARG_VALUE },
{}
};
- int c;
+ int c, r;
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hH:M:p:a", options, NULL)) >= 0)
switch (c) {
case 'h':
- help();
- return 0;
+ return help();
case ARG_VERSION:
return version();
@@ -382,6 +792,30 @@ static int parse_argv(int argc, char *argv[]) {
arg_no_pager = true;
break;
+ case ARG_MONITOR:
+ arg_monitor = true;
+ break;
+
+ case 'p': {
+ r = strv_extend(&arg_property, optarg);
+ if (r < 0)
+ return log_oom();
+
+ /* If the user asked for a particular
+ * property, show it to him, even if it is
+ * empty. */
+ arg_all = true;
+ break;
+ }
+
+ case 'a':
+ arg_all = true;
+ break;
+
+ case ARG_VALUE:
+ arg_value = true;
+ break;
+
case '?':
return -EINVAL;
@@ -394,82 +828,21 @@ static int parse_argv(int argc, char *argv[]) {
static int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-time", EQUAL, 2, set_time },
- { "set-timezone", EQUAL, 2, set_timezone },
- { "list-timezones", EQUAL, 1, list_timezones },
- { "set-local-rtc", EQUAL, 2, set_local_rtc },
- { "set-ntp", EQUAL, 2, set_ntp, },
+ static const Verb verbs[] = {
+ { "status", VERB_ANY, 1, VERB_DEFAULT, show_status },
+ { "show", VERB_ANY, 1, 0, show_properties },
+ { "set-time", 2, 2, 0, set_time },
+ { "set-timezone", 2, 2, 0, set_timezone },
+ { "list-timezones", VERB_ANY, 1, 0, list_timezones },
+ { "set-local-rtc", 2, 2, 0, set_local_rtc },
+ { "set-ntp", 2, 2, 0, set_ntp },
+ { "timesync-status", VERB_ANY, 1, 0, show_timesync_status },
+ { "show-timesync", VERB_ANY, 1, 0, show_timesync },
+ { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */
+ {}
};
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
+ return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char *argv[]) {
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 822835cce9..82eb213e95 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
@@ -34,33 +16,169 @@
#include "def.h"
#include "fileio-label.h"
#include "fs-util.h"
+#include "hashmap.h"
+#include "list.h"
#include "path-util.h"
#include "selinux-util.h"
+#include "string-util.h"
#include "strv.h"
+#include "unit-def.h"
+#include "unit-name.h"
#include "user-util.h"
#include "util.h"
#define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
-static BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map timedated_errors[] = {
- SD_BUS_ERROR_MAP("org.freedesktop.timedate1.NoNTPSupport", EOPNOTSUPP),
- SD_BUS_ERROR_MAP_END
-};
+typedef struct UnitStatusInfo {
+ char *name;
+ char *load_state;
+ char *unit_file_state;
+ char *active_state;
+
+ LIST_FIELDS(struct UnitStatusInfo, units);
+} UnitStatusInfo;
typedef struct Context {
char *zone;
bool local_rtc;
- bool can_ntp;
- bool use_ntp;
Hashmap *polkit_registry;
+
+ LIST_HEAD(UnitStatusInfo, units);
} Context;
+static void unit_status_info_clear(UnitStatusInfo *p) {
+ assert(p);
+
+ p->load_state = mfree(p->load_state);
+ p->unit_file_state = mfree(p->unit_file_state);
+ p->active_state = mfree(p->active_state);
+}
+
+static void unit_status_info_free(UnitStatusInfo *p) {
+ assert(p);
+
+ unit_status_info_clear(p);
+ free(p->name);
+ free(p);
+}
+
static void context_free(Context *c) {
+ UnitStatusInfo *p;
+
assert(c);
free(c->zone);
bus_verify_polkit_async_registry_free(c->polkit_registry);
+
+ while ((p = c->units)) {
+ LIST_REMOVE(units, c->units, p);
+ unit_status_info_free(p);
+ }
+}
+
+static int context_add_ntp_service(Context *c, const char *s) {
+ UnitStatusInfo *u;
+
+ if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
+ return -EINVAL;
+
+ /* Do not add this if it is already listed */
+ LIST_FOREACH(units, u, c->units)
+ if (streq(u->name, s))
+ return 0;
+
+ u = new0(UnitStatusInfo, 1);
+ if (!u)
+ return -ENOMEM;
+
+ u->name = strdup(s);
+ if (!u->name) {
+ free(u);
+ return -ENOMEM;
+ }
+
+ LIST_APPEND(units, c->units, u);
+
+ return 0;
+}
+
+static int context_parse_ntp_services(Context *c) {
+ const char *env, *p;
+ int r;
+
+ assert(c);
+
+ env = getenv("SYSTEMD_TIMEDATED_NTP_SERVICES");
+ if (!env) {
+ r = context_add_ntp_service(c, "systemd-timesyncd.service");
+ if (r < 0)
+ log_warning_errno(r, "Failed to add NTP service \"systemd-timesyncd.service\", ignoring: %m");
+
+ return 0;
+ }
+
+ for (p = env;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&p, &word, ":", 0);
+ if (r == 0)
+ break;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_error("Invalid syntax, ignoring: %s", env);
+ break;
+ }
+
+ r = context_add_ntp_service(c, word);
+ if (r < 0)
+ log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word);
+ }
+
+ return 0;
+}
+
+static int context_ntp_service_is_active(Context *c) {
+ UnitStatusInfo *info;
+ int count = 0;
+
+ assert(c);
+
+ /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
+
+ LIST_FOREACH(units, info, c->units)
+ count += streq_ptr(info->active_state, "active");
+
+ return count;
+}
+
+static int context_ntp_service_is_enabled(Context *c) {
+ UnitStatusInfo *info;
+ int count = 0;
+
+ assert(c);
+
+ /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
+
+ LIST_FOREACH(units, info, c->units)
+ count += STRPTR_IN_SET(info->unit_file_state, "enabled", "enabled-runtime");
+
+ return count;
+}
+
+static int context_ntp_service_exists(Context *c) {
+ UnitStatusInfo *info;
+ int count = 0;
+
+ assert(c);
+
+ /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
+
+ LIST_FOREACH(units, info, c->units)
+ count += streq_ptr(info->load_state, "loaded");
+
+ return count;
}
static int context_read_data(Context *c) {
@@ -176,81 +294,94 @@ static int context_write_data_local_rtc(Context *c) {
return write_string_file_atomic_label("/etc/adjtime", w);
}
-static int context_read_ntp(Context *c, sd_bus *bus) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *s;
+static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m) {
+ static const struct bus_properties_map map[] = {
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
+ { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) },
+ {}
+ };
+ static sd_bus_message *_m = NULL;
+ UnitStatusInfo *u;
int r;
assert(c);
assert(bus);
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnitFileState",
- &error,
- &reply,
- "s",
- "systemd-timesyncd.service");
+ /* Suppress multiple call of context_update_ntp_status() within single DBus transaction. */
+ if (m && m == _m)
+ return 0;
- if (r < 0) {
- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND) ||
- sd_bus_error_has_name(&error, "org.freedesktop.systemd1.LoadFailed") ||
- sd_bus_error_has_name(&error, "org.freedesktop.systemd1.NoSuchUnit"))
- return 0;
+ _m = m;
- return r;
- }
+ LIST_FOREACH(units, u, c->units) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *path = NULL;
- r = sd_bus_message_read(reply, "s", &s);
- if (r < 0)
- return r;
+ unit_status_info_clear(u);
+
+ path = unit_dbus_path_from_name(u->name);
+ if (!path)
+ return -ENOMEM;
- c->can_ntp = true;
- c->use_ntp = STR_IN_SET(s, "enabled", "enabled-runtime");
+ r = bus_map_all_properties(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ map,
+ BUS_MAP_STRDUP,
+ &error,
+ NULL,
+ u);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
+ }
return 0;
}
-static int context_start_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
+static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) {
int r;
+ assert(u);
assert(bus);
assert(error);
+ /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
+
+ if (streq(u->active_state, "active") == start)
+ return 0;
+
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
- enabled ? "StartUnit" : "StopUnit",
+ start ? "StartUnit" : "StopUnit",
error,
NULL,
"ss",
- "systemd-timesyncd.service",
+ u->name,
"replace");
- if (r < 0) {
- if (sd_bus_error_has_name(error, SD_BUS_ERROR_FILE_NOT_FOUND) ||
- sd_bus_error_has_name(error, "org.freedesktop.systemd1.LoadFailed") ||
- sd_bus_error_has_name(error, "org.freedesktop.systemd1.NoSuchUnit"))
- return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported.");
-
+ if (r < 0)
return r;
- }
return 0;
}
-static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
+static int unit_enable_or_disable(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool enable) {
int r;
+ assert(u);
assert(bus);
assert(error);
- if (enabled)
+ /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
+
+ if (streq(u->unit_file_state, "enabled") == enable)
+ return 0;
+
+ if (enable)
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
@@ -260,7 +391,7 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
error,
NULL,
"asbb", 1,
- "systemd-timesyncd.service",
+ u->name,
false, true);
else
r = sd_bus_call_method(
@@ -272,15 +403,10 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
error,
NULL,
"asb", 1,
- "systemd-timesyncd.service",
+ u->name,
false);
-
- if (r < 0) {
- if (sd_bus_error_has_name(error, SD_BUS_ERROR_FILE_NOT_FOUND))
- return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported.");
-
+ if (r < 0)
return r;
- }
r = sd_bus_call_method(
bus,
@@ -291,12 +417,14 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) {
error,
NULL,
NULL);
- if (r < 0)
- return r;
-
+ if (r < 0)
+ return r;
return 0;
}
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_time, "t", now(CLOCK_REALTIME));
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_ntp_sync, "b", ntp_synced());
+
static int property_get_rtc_time(
sd_bus *bus,
const char *path,
@@ -326,7 +454,7 @@ static int property_get_rtc_time(
return sd_bus_message_append(reply, "t", t);
}
-static int property_get_time(
+static int property_get_can_ntp(
sd_bus *bus,
const char *path,
const char *interface,
@@ -335,10 +463,23 @@ static int property_get_time(
void *userdata,
sd_bus_error *error) {
- return sd_bus_message_append(reply, "t", now(CLOCK_REALTIME));
+ Context *c = userdata;
+ int r;
+
+ assert(c);
+ assert(bus);
+ assert(property);
+ assert(reply);
+ assert(error);
+
+ r = context_update_ntp_status(c, bus, reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_append(reply, "b", context_ntp_service_exists(c) > 0);
}
-static int property_get_ntp_sync(
+static int property_get_ntp(
sd_bus *bus,
const char *path,
const char *interface,
@@ -347,15 +488,26 @@ static int property_get_ntp_sync(
void *userdata,
sd_bus_error *error) {
- return sd_bus_message_append(reply, "b", ntp_synced());
+ Context *c = userdata;
+ int r;
+
+ assert(c);
+ assert(bus);
+ assert(property);
+ assert(reply);
+ assert(error);
+
+ r = context_update_ntp_status(c, bus, reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_append(reply, "b", context_ntp_service_is_active(c) > 0);
}
static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Context *c = userdata;
+ int interactive, r;
const char *z;
- int interactive;
- char *t;
- int r;
assert(m);
assert(c);
@@ -364,7 +516,7 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *
if (r < 0)
return r;
- if (!timezone_is_valid(z))
+ if (!timezone_is_valid(z, LOG_DEBUG))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid time zone '%s'", z);
if (streq_ptr(z, c->zone))
@@ -384,12 +536,9 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- t = strdup(z);
- if (!t)
- return -ENOMEM;
-
- free(c->zone);
- c->zone = t;
+ r = free_and_strdup(&c->zone, z);
+ if (r < 0)
+ return r;
/* 1. Write new configuration file */
r = context_write_data_timezone(c);
@@ -398,24 +547,33 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *
return sd_bus_error_set_errnof(error, r, "Failed to set time zone: %m");
}
- /* 2. Tell the kernel our timezone */
- clock_set_timezone(NULL);
+ /* 2. Make glibc notice the new timezone */
+ tzset();
+
+ /* 3. Tell the kernel our timezone */
+ r = clock_set_timezone(NULL);
+ if (r < 0)
+ log_debug_errno(r, "Failed to tell kernel about timezone, ignoring: %m");
if (c->local_rtc) {
struct timespec ts;
struct tm *tm;
- /* 3. Sync RTC from system clock, with the new delta */
+ /* 4. Sync RTC from system clock, with the new delta */
assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
assert_se(tm = localtime(&ts.tv_sec));
- clock_set_hwclock(tm);
+
+ r = clock_set_hwclock(tm);
+ if (r < 0)
+ log_debug_errno(r, "Failed to sync time to hardware clock, ignoring: %m");
}
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_TIMEZONE_CHANGE_STR,
"TIMEZONE=%s", c->zone,
- LOG_MESSAGE("Changed time zone to '%s'.", c->zone),
- NULL);
+ "TIMEZONE_SHORTNAME=%s", tzname[daylight],
+ "DAYLIGHT=%i", daylight,
+ LOG_MESSAGE("Changed time zone to '%s' (%s).", c->zone, tzname[daylight]));
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone", NULL);
@@ -462,7 +620,9 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
}
/* 2. Tell the kernel our timezone */
- clock_set_timezone(NULL);
+ r = clock_set_timezone(NULL);
+ if (r < 0)
+ log_debug_errno(r, "Failed to tell kernel about timezone, ignoring: %m");
/* 3. Synchronize clocks */
assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
@@ -470,27 +630,25 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
if (fix_system) {
struct tm tm;
- /* Sync system clock from RTC; first,
- * initialize the timezone fields of
- * struct tm. */
+ /* Sync system clock from RTC; first, initialize the timezone fields of struct tm. */
if (c->local_rtc)
tm = *localtime(&ts.tv_sec);
else
tm = *gmtime(&ts.tv_sec);
- /* Override the main fields of
- * struct tm, but not the timezone
- * fields */
- if (clock_get_hwclock(&tm) >= 0) {
-
- /* And set the system clock
- * with this */
+ /* Override the main fields of struct tm, but not the timezone fields */
+ r = clock_get_hwclock(&tm);
+ if (r < 0)
+ log_debug_errno(r, "Failed to get hardware clock, ignoring: %m");
+ else {
+ /* And set the system clock with this */
if (c->local_rtc)
ts.tv_sec = mktime(&tm);
else
ts.tv_sec = timegm(&tm);
- clock_settime(CLOCK_REALTIME, &ts);
+ if (clock_settime(CLOCK_REALTIME, &ts) < 0)
+ log_debug_errno(errno, "Failed to update system clock, ignoring: %m");
}
} else {
@@ -502,7 +660,9 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
else
tm = gmtime(&ts.tv_sec);
- clock_set_hwclock(tm);
+ r = clock_set_hwclock(tm);
+ if (r < 0)
+ log_debug_errno(r, "Failed to sync time to hardware clock, ignoring: %m");
}
log_info("RTC configured to %s time.", c->local_rtc ? "local" : "UTC");
@@ -513,19 +673,23 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
}
static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- int relative, interactive;
+ sd_bus *bus = sd_bus_message_get_bus(m);
+ int relative, interactive, r;
Context *c = userdata;
int64_t utc;
struct timespec ts;
usec_t start;
struct tm* tm;
- int r;
assert(m);
assert(c);
- if (c->use_ntp)
- return sd_bus_error_setf(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled");
+ r = context_update_ntp_status(c, bus, m);
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Failed to update context: %m");
+
+ if (context_ntp_service_is_active(c) > 0)
+ return sd_bus_error_set(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled");
/* this only gets used if dbus does not provide a timestamp */
start = now(CLOCK_MONOTONIC);
@@ -535,7 +699,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
return r;
if (!relative && utc <= 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid absolute time");
+ return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid absolute time");
if (relative && utc == 0)
return sd_bus_reply_method_return(m, NULL);
@@ -548,7 +712,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
if ((utc > 0 && x < n) ||
(utc < 0 && x > n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Time value overflow");
+ return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Time value overflow");
timespec_store(&ts, x);
} else
@@ -587,31 +751,39 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
tm = localtime(&ts.tv_sec);
else
tm = gmtime(&ts.tv_sec);
- clock_set_hwclock(tm);
+
+ r = clock_set_hwclock(tm);
+ if (r < 0)
+ log_debug_errno(r, "Failed to update hardware clock, ignoring: %m");
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR,
"REALTIME="USEC_FMT, timespec_load(&ts),
- LOG_MESSAGE("Changed local time to %s", ctime(&ts.tv_sec)),
- NULL);
+ LOG_MESSAGE("Changed local time to %s", ctime(&ts.tv_sec)));
return sd_bus_reply_method_return(m, NULL);
}
static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- int enabled, interactive;
+ sd_bus *bus = sd_bus_message_get_bus(m);
Context *c = userdata;
- int r;
+ UnitStatusInfo *u;
+ int enable, interactive, q, r;
assert(m);
+ assert(bus);
assert(c);
- r = sd_bus_message_read(m, "bb", &enabled, &interactive);
+ r = sd_bus_message_read(m, "bb", &enable, &interactive);
if (r < 0)
return r;
- if ((bool)enabled == c->use_ntp)
- return sd_bus_reply_method_return(m, NULL);
+ r = context_update_ntp_status(c, bus, m);
+ if (r < 0)
+ return r;
+
+ if (context_ntp_service_exists(c) <= 0)
+ return sd_bus_error_set(error, BUS_ERROR_NO_NTP_SUPPORT, "NTP not supported");
r = bus_verify_polkit_async(
m,
@@ -627,18 +799,49 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
if (r == 0)
return 1;
- r = context_enable_ntp(sd_bus_message_get_bus(m), error, enabled);
- if (r < 0)
- return r;
+ if (!enable)
+ LIST_FOREACH(units, u, c->units) {
+ if (!streq(u->load_state, "loaded"))
+ continue;
+
+ q = unit_enable_or_disable(u, bus, error, enable);
+ if (q < 0)
+ r = q;
+
+ q = unit_start_or_stop(u, bus, error, enable);
+ if (q < 0)
+ r = q;
+ }
+
+ else if (context_ntp_service_is_enabled(c) <= 0)
+ LIST_FOREACH(units, u, c->units) {
+ if (!streq(u->load_state, "loaded"))
+ continue;
+
+ r = unit_enable_or_disable(u, bus, error, enable);
+ if (r < 0)
+ continue;
+
+ r = unit_start_or_stop(u, bus, error, enable);
+ break;
+ }
+
+ else if (context_ntp_service_is_active(c) <= 0)
+ LIST_FOREACH(units, u, c->units) {
+ if (!streq(u->load_state, "loaded") ||
+ !streq(u->unit_file_state, "enabled"))
+ continue;
+
+ r = unit_start_or_stop(u, bus, error, enable);
+ break;
+ }
- r = context_start_ntp(sd_bus_message_get_bus(m), error, enabled);
if (r < 0)
return r;
- c->use_ntp = enabled;
- log_info("Set NTP to %sd", enable_disable(enabled));
+ log_info("Set NTP to %sd", enable_disable(enable));
- (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
+ (void) sd_bus_emit_properties_changed(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
return sd_bus_reply_method_return(m, NULL);
}
@@ -647,8 +850,8 @@ static const sd_bus_vtable timedate_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("LocalRTC", "b", bus_property_get_bool, offsetof(Context, local_rtc), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("CanNTP", "b", bus_property_get_bool, offsetof(Context, can_ntp), 0),
- SD_BUS_PROPERTY("NTP", "b", bus_property_get_bool, offsetof(Context, use_ntp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("CanNTP", "b", property_get_can_ntp, 0, 0),
+ SD_BUS_PROPERTY("NTP", "b", property_get_ntp, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("NTPSynchronized", "b", property_get_ntp_sync, 0, 0),
SD_BUS_PROPERTY("TimeUSec", "t", property_get_time, 0, 0),
SD_BUS_PROPERTY("RTCTimeUSec", "t", property_get_rtc_time, 0, 0),
@@ -683,8 +886,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
- *_bus = bus;
- bus = NULL;
+ *_bus = TAKE_PTR(bus);
return 0;
}
@@ -727,11 +929,9 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = context_read_ntp(&context, bus);
- if (r < 0) {
- log_error_errno(r, "Failed to determine whether NTP is enabled: %m");
+ r = context_parse_ntp_services(&context);
+ if (r < 0)
goto finish;
- }
r = bus_event_loop_with_idle(event, bus, "org.freedesktop.timedate1", DEFAULT_EXIT_USEC, NULL, NULL);
if (r < 0) {
diff --git a/src/timesync/meson.build b/src/timesync/meson.build
index e8bd3d59a9..b79ef08277 100644
--- a/src/timesync/meson.build
+++ b/src/timesync/meson.build
@@ -1,26 +1,14 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
systemd_timesyncd_sources = files('''
timesyncd.c
- timesyncd-manager.c
- timesyncd-manager.h
+ timesyncd-bus.c
+ timesyncd-bus.h
timesyncd-conf.c
timesyncd-conf.h
+ timesyncd-manager.c
+ timesyncd-manager.h
+ timesyncd-ntp-message.h
timesyncd-server.c
timesyncd-server.h
'''.split())
@@ -40,6 +28,10 @@ if conf.get('ENABLE_TIMESYNCD') == 1
configuration : substs)
install_data(timesyncd_conf,
install_dir : pkgsysconfdir)
+ install_data('org.freedesktop.timesync1.conf',
+ install_dir : dbuspolicydir)
+ install_data('org.freedesktop.timesync1.service',
+ install_dir : dbussystemservicedir)
endif
############################################################
diff --git a/src/timesync/org.freedesktop.timesync1.conf b/src/timesync/org.freedesktop.timesync1.conf
new file mode 100644
index 0000000000..eccdbec718
--- /dev/null
+++ b/src/timesync/org.freedesktop.timesync1.conf
@@ -0,0 +1,42 @@
+<?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="systemd-timesync">
+ <allow own="org.freedesktop.timesync1"/>
+ <allow send_destination="org.freedesktop.timesync1"/>
+ <allow receive_sender="org.freedesktop.timesync1"/>
+ </policy>
+
+ <policy context="default">
+ <deny send_destination="org.freedesktop.timesync1"/>
+
+ <allow send_destination="org.freedesktop.timesync1"
+ send_interface="org.freedesktop.DBus.Introspectable"/>
+
+ <allow send_destination="org.freedesktop.timesync1"
+ send_interface="org.freedesktop.DBus.Peer"/>
+
+ <allow send_destination="org.freedesktop.timesync1"
+ send_interface="org.freedesktop.DBus.Properties"
+ send_member="Get"/>
+
+ <allow send_destination="org.freedesktop.timesync1"
+ send_interface="org.freedesktop.DBus.Properties"
+ send_member="GetAll"/>
+
+ <allow receive_sender="org.freedesktop.timesync1"/>
+ </policy>
+
+</busconfig>
diff --git a/src/timesync/org.freedesktop.timesync1.service b/src/timesync/org.freedesktop.timesync1.service
new file mode 100644
index 0000000000..84b4b4f973
--- /dev/null
+++ b/src/timesync/org.freedesktop.timesync1.service
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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.timesync1
+Exec=/bin/false
+User=root
+SystemdService=dbus-org.freedesktop.timesync1.service
diff --git a/src/timesync/test-timesync.c b/src/timesync/test-timesync.c
index 7d5cd38078..a045eeeec1 100644
--- a/src/timesync/test-timesync.c
+++ b/src/timesync/test-timesync.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2017 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
/* Some unit tests for the helper functions in timesyncd. */
@@ -37,9 +19,9 @@ static void test_manager_parse_string(void) {
assert_se(m->have_fallbacks);
assert_se(manager_parse_fallback_string(m, NTP_SERVERS) == 0);
- assert_se(manager_parse_server_string(m, SERVER_SYSTEM, "time1.foobar.com time2.foobar.com") == 0);
- assert_se(manager_parse_server_string(m, SERVER_FALLBACK, "time1.foobar.com time2.foobar.com") == 0);
- assert_se(manager_parse_server_string(m, SERVER_LINK, "time1.foobar.com time2.foobar.com") == 0);
+ assert_se(manager_parse_server_string(m, SERVER_SYSTEM, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0);
+ assert_se(manager_parse_server_string(m, SERVER_FALLBACK, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0);
+ assert_se(manager_parse_server_string(m, SERVER_LINK, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0);
}
int main(int argc, char **argv) {
diff --git a/src/timesync/timesyncd-bus.c b/src/timesync/timesyncd-bus.c
new file mode 100644
index 0000000000..f2527f52e4
--- /dev/null
+++ b/src/timesync/timesyncd-bus.c
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-internal.h"
+#include "bus-protocol.h"
+#include "bus-util.h"
+#include "in-addr-util.h"
+#include "log.h"
+#include "macro.h"
+#include "time-util.h"
+#include "timesyncd-bus.h"
+
+static int property_get_servers(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ServerName *p, **s = userdata;
+ int r;
+
+ assert(s);
+ assert(bus);
+ assert(reply);
+
+ r = sd_bus_message_open_container(reply, 'a', "s");
+ if (r < 0)
+ return r;
+
+ LIST_FOREACH(names, p, *s) {
+ r = sd_bus_message_append(reply, "s", p->string);
+ if (r < 0)
+ return r;
+ }
+
+ return sd_bus_message_close_container(reply);
+}
+
+static int property_get_current_server_name(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ServerName **s = userdata;
+
+ assert(s);
+ assert(bus);
+ assert(reply);
+
+ return sd_bus_message_append(reply, "s", *s ? (*s)->string : NULL);
+}
+
+static int property_get_current_server_address(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ServerAddress *a;
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(userdata);
+
+ a = *(ServerAddress **) userdata;
+
+ if (!a)
+ return sd_bus_message_append(reply, "(iay)", AF_UNSPEC, 0);
+
+ r = sd_bus_message_open_container(reply, 'r', "iay");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "i", a->sockaddr.sa.sa_family);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append_array(reply, 'y', &a->sockaddr.in.sin_addr, FAMILY_ADDRESS_SIZE(a->sockaddr.sa.sa_family));
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_close_container(reply);
+}
+
+static usec_t ntp_ts_short_to_usec(const struct ntp_ts_short *ts) {
+ return be16toh(ts->sec) * USEC_PER_SEC + (be16toh(ts->frac) * USEC_PER_SEC) / (usec_t) 0x10000ULL;
+}
+
+static usec_t ntp_ts_to_usec(const struct ntp_ts *ts) {
+ return (be32toh(ts->sec) - OFFSET_1900_1970) * USEC_PER_SEC + (be32toh(ts->frac) * USEC_PER_SEC) / (usec_t) 0x100000000ULL;
+}
+
+static int property_get_ntp_message(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Manager *m = userdata;
+ int r;
+
+ assert(m);
+ assert(reply);
+
+ r = sd_bus_message_open_container(reply, 'r', "uuuuittayttttbtt");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "uuuuitt",
+ NTP_FIELD_LEAP(m->ntpmsg.field),
+ NTP_FIELD_VERSION(m->ntpmsg.field),
+ NTP_FIELD_MODE(m->ntpmsg.field),
+ m->ntpmsg.stratum,
+ m->ntpmsg.precision,
+ ntp_ts_short_to_usec(&m->ntpmsg.root_delay),
+ ntp_ts_short_to_usec(&m->ntpmsg.root_dispersion));
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append_array(reply, 'y', m->ntpmsg.refid, 4);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "ttttbtt",
+ timespec_load(&m->origin_time),
+ ntp_ts_to_usec(&m->ntpmsg.recv_time),
+ ntp_ts_to_usec(&m->ntpmsg.trans_time),
+ timespec_load(&m->dest_time),
+ m->spike,
+ m->packet_count,
+ (usec_t) (m->samples_jitter * USEC_PER_SEC));
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_close_container(reply);
+}
+
+static const sd_bus_vtable manager_vtable[] = {
+ SD_BUS_VTABLE_START(0),
+
+ SD_BUS_PROPERTY("LinkNTPServers", "as", property_get_servers, offsetof(Manager, link_servers), 0),
+ SD_BUS_PROPERTY("SystemNTPServers", "as", property_get_servers, offsetof(Manager, system_servers), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("FallbackNTPServers", "as", property_get_servers, offsetof(Manager, fallback_servers), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ServerName", "s", property_get_current_server_name, offsetof(Manager, current_server_name), 0),
+ SD_BUS_PROPERTY("ServerAddress", "(iay)", property_get_current_server_address, offsetof(Manager, current_server_address), 0),
+ SD_BUS_PROPERTY("RootDistanceMaxUSec", "t", bus_property_get_usec, offsetof(Manager, max_root_distance_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("PollIntervalMinUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_min_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("PollIntervalMaxUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("PollIntervalUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_usec), 0),
+ SD_BUS_PROPERTY("NTPMessage", "(uuuuittayttttbtt)", property_get_ntp_message, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("Frequency", "x", NULL, offsetof(Manager, drift_freq), 0),
+
+ SD_BUS_VTABLE_END
+};
+
+int manager_connect_bus(Manager *m) {
+ int r;
+
+ assert(m);
+
+ if (m->bus)
+ return 0;
+
+ r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-timesync");
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to bus: %m");
+
+ r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/timesync1", "org.freedesktop.timesync1.Manager", manager_vtable, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add manager object vtable: %m");
+
+ r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.timesync1", 0, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to request name: %m");
+
+ r = sd_bus_attach_event(m->bus, m->event, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach bus to event loop: %m");
+
+ return 0;
+}
diff --git a/src/timesync/timesyncd-bus.h b/src/timesync/timesyncd-bus.h
new file mode 100644
index 0000000000..6670ffbc36
--- /dev/null
+++ b/src/timesync/timesyncd-bus.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "timesyncd-manager.h"
+
+int manager_connect_bus(Manager *m);
diff --git a/src/timesync/timesyncd-conf.c b/src/timesync/timesyncd-conf.c
index 124d03da0b..a26c2dad7f 100644
--- a/src/timesync/timesyncd-conf.c
+++ b/src/timesync/timesyncd-conf.c
@@ -1,25 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Kay Sievers, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "def.h"
+#include "dns-domain.h"
#include "extract-word.h"
#include "string-util.h"
#include "timesyncd-conf.h"
@@ -49,6 +32,14 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
if (r == 0)
break;
+ r = dns_name_is_valid_or_address(word);
+ if (r < 0)
+ return log_error_errno(r, "Failed to check validity of NTP server name or address '%s': %m", word);
+ if (r == 0) {
+ log_error("Invalid NTP server name or address, ignoring: %s", word);
+ continue;
+ }
+
/* Filter out duplicates */
LIST_FOREACH(names, n, first)
if (streq_ptr(n->string, word)) {
diff --git a/src/timesync/timesyncd-conf.h b/src/timesync/timesyncd-conf.h
index 8252298fe0..ebdb143f0b 100644
--- a/src/timesync/timesyncd-conf.h
+++ b/src/timesync/timesyncd-conf.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Kay Sievers, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "conf-parser.h"
#include "timesyncd-manager.h"
@@ -27,7 +9,7 @@ const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, GPERF_LEN_T
int manager_parse_server_string(Manager *m, ServerType type, const char *string);
-int config_parse_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_servers);
int manager_parse_config_file(Manager *m);
int manager_parse_fallback_string(Manager *m, const char *string);
diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c
index 7743036023..2b731af9e3 100644
--- a/src/timesync/timesyncd-manager.c
+++ b/src/timesync/timesyncd-manager.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Kay Sievers, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <math.h>
@@ -33,6 +15,7 @@
#include "sd-daemon.h"
#include "alloc-util.h"
+#include "dns-domain.h"
#include "fd-util.h"
#include "fs-util.h"
#include "list.h"
@@ -41,7 +24,6 @@
#include "network-util.h"
#include "ratelimit.h"
#include "socket-util.h"
-#include "sparse-endian.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -63,59 +45,18 @@
*/
#define NTP_MAX_ADJUST 0.4
-/* NTP protocol, packet header */
-#define NTP_LEAP_PLUSSEC 1
-#define NTP_LEAP_MINUSSEC 2
-#define NTP_LEAP_NOTINSYNC 3
-#define NTP_MODE_CLIENT 3
-#define NTP_MODE_SERVER 4
-#define NTP_FIELD_LEAP(f) (((f) >> 6) & 3)
-#define NTP_FIELD_VERSION(f) (((f) >> 3) & 7)
-#define NTP_FIELD_MODE(f) ((f) & 7)
-#define NTP_FIELD(l, v, m) (((l) << 6) | ((v) << 3) | (m))
-
/* Default of maximum acceptable root distance in microseconds. */
#define NTP_MAX_ROOT_DISTANCE (5 * USEC_PER_SEC)
/* Maximum number of missed replies before selecting another source. */
#define NTP_MAX_MISSED_REPLIES 2
-/*
- * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
- * in seconds relative to 0h on 1 January 1900."
- */
-#define OFFSET_1900_1970 UINT64_C(2208988800)
-
#define RETRY_USEC (30*USEC_PER_SEC)
#define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC)
#define RATELIMIT_BURST 10
#define TIMEOUT_USEC (10*USEC_PER_SEC)
-struct ntp_ts {
- be32_t sec;
- be32_t frac;
-} _packed_;
-
-struct ntp_ts_short {
- be16_t sec;
- be16_t frac;
-} _packed_;
-
-struct ntp_msg {
- uint8_t field;
- uint8_t stratum;
- int8_t poll;
- int8_t precision;
- struct ntp_ts_short root_delay;
- struct ntp_ts_short root_dispersion;
- char refid[4];
- struct ntp_ts reference_time;
- struct ntp_ts origin_time;
- struct ntp_ts recv_time;
- struct ntp_ts trans_time;
-} _packed_;
-
static int manager_arm_timer(Manager *m, usec_t next);
static int manager_clock_watch_setup(Manager *m);
static int manager_listen_setup(Manager *m);
@@ -279,11 +220,6 @@ static int manager_clock_watch(sd_event_source *source, int fd, uint32_t revents
/* wake up when the system time changes underneath us */
static int manager_clock_watch_setup(Manager *m) {
-
- struct itimerspec its = {
- .it_value.tv_sec = TIME_T_MAX
- };
-
int r;
assert(m);
@@ -291,12 +227,9 @@ static int manager_clock_watch_setup(Manager *m) {
m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
safe_close(m->clock_watch_fd);
- m->clock_watch_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+ m->clock_watch_fd = time_change_fd();
if (m->clock_watch_fd < 0)
- return log_error_errno(errno, "Failed to create timerfd: %m");
-
- if (timerfd_settime(m->clock_watch_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0)
- return log_error_errno(errno, "Failed to set up timerfd: %m");
+ return log_error_errno(m->clock_watch_fd, "Failed to create timerfd: %m");
r = sd_event_add_io(m->event, &m->event_clock_watch, m->clock_watch_fd, EPOLLIN, manager_clock_watch, m);
if (r < 0)
@@ -368,19 +301,20 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
/* If touch fails, there isn't much we can do. Maybe it'll work next time. */
(void) touch("/var/lib/systemd/timesync/clock");
+ (void) touch("/run/systemd/timesync/synchronized");
- m->drift_ppm = tmx.freq / 65536;
+ m->drift_freq = tmx.freq;
log_debug(" status : %04i %s\n"
" time now : %"PRI_TIME".%03"PRI_USEC"\n"
" constant : %"PRI_TIMEX"\n"
" offset : %+.3f sec\n"
- " freq offset : %+"PRI_TIMEX" (%i ppm)\n",
+ " freq offset : %+"PRI_TIMEX" (%+"PRI_TIMEX" ppm)\n",
tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync",
tmx.time.tv_sec, tmx.time.tv_usec / NSEC_PER_MSEC,
tmx.constant,
(double)tmx.offset / NSEC_PER_SEC,
- tmx.freq, m->drift_ppm);
+ tmx.freq, tmx.freq / 65536);
return 0;
}
@@ -488,7 +422,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
.msg_namelen = sizeof(server_addr),
};
struct cmsghdr *cmsg;
- struct timespec *recv_time;
+ struct timespec *recv_time = NULL;
ssize_t len;
double origin, receive, trans, dest;
double delay, offset;
@@ -527,7 +461,6 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
return 0;
}
- recv_time = NULL;
CMSG_FOREACH(cmsg, &msghdr) {
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
@@ -665,10 +598,18 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
log_error_errno(r, "Failed to call clock_adjtime(): %m");
}
- log_debug("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+ippm%s",
- m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_ppm,
+ /* Save NTP response */
+ m->ntpmsg = ntpmsg;
+ m->origin_time = m->trans_time;
+ m->dest_time = *recv_time;
+ m->spike = spike;
+
+ log_debug("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+"PRI_TIMEX"ppm%s",
+ m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_freq / 65536,
spike ? " (ignored)" : "");
+ (void) sd_bus_emit_properties_changed(m->bus, "/org/freedesktop/timesync1", "org.freedesktop.timesync1.Manager", "NTPMessage", NULL);
+
if (!m->good) {
_cleanup_free_ char *pretty = NULL;
@@ -851,7 +792,7 @@ int manager_connect(Manager *m) {
manager_disconnect(m);
m->event_retry = sd_event_source_unref(m->event_retry);
- if (!ratelimit_test(&m->ratelimit)) {
+ if (!ratelimit_below(&m->ratelimit)) {
log_debug("Slowing down attempts to contact servers.");
r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m);
@@ -999,6 +940,8 @@ void manager_free(Manager *m) {
sd_resolve_unref(m->resolve);
sd_event_unref(m->event);
+ sd_bus_unref(m->bus);
+
free(m);
}
@@ -1012,8 +955,13 @@ static int manager_network_read_link_servers(Manager *m) {
assert(m);
r = sd_network_get_ntp(&ntp);
- if (r < 0)
+ if (r < 0) {
+ if (r == -ENOMEM)
+ log_oom();
+ else
+ log_debug_errno(r, "Failed to get link NTP servers: %m");
goto clear;
+ }
LIST_FOREACH(names, n, m->link_servers)
n->marked = true;
@@ -1021,6 +969,15 @@ static int manager_network_read_link_servers(Manager *m) {
STRV_FOREACH(i, ntp) {
bool found = false;
+ r = dns_name_is_valid_or_address(*i);
+ if (r < 0) {
+ log_error_errno(r, "Failed to check validity of NTP server name or address '%s': %m", *i);
+ goto clear;
+ } else if (r == 0) {
+ log_error("Invalid NTP server name or address, ignoring: %s", *i);
+ continue;
+ }
+
LIST_FOREACH(names, n, m->link_servers)
if (streq(n->string, *i)) {
n->marked = false;
@@ -1030,8 +987,10 @@ static int manager_network_read_link_servers(Manager *m) {
if (!found) {
r = server_name_new(m, NULL, SERVER_LINK, *i);
- if (r < 0)
+ if (r < 0) {
+ log_oom();
goto clear;
+ }
changed = true;
}
@@ -1050,6 +1009,12 @@ clear:
return r;
}
+static bool manager_is_connected(Manager *m) {
+ /* Return true when the manager is sending a request, resolving a server name, or
+ * in a poll interval. */
+ return m->server_socket >= 0 || m->resolve_query || m->event_timer;
+}
+
static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
bool changed, connected, online;
@@ -1059,19 +1024,20 @@ static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t re
sd_network_monitor_flush(m->network_monitor);
+ /* When manager_network_read_link_servers() failed, we assume that the servers are changed. */
changed = !!manager_network_read_link_servers(m);
/* check if the machine is online */
online = network_is_online();
/* check if the client is currently connected */
- connected = m->server_socket >= 0 || m->resolve_query || m->exhausted_servers;
+ connected = manager_is_connected(m);
if (connected && !online) {
log_info("No network connectivity, watching for changes.");
manager_disconnect(m);
- } else if (!connected && online && changed) {
+ } else if ((!connected || changed) && online) {
log_info("Network configuration changed, trying to establish connection.");
if (m->current_server_address)
@@ -1152,10 +1118,9 @@ int manager_new(Manager **ret) {
if (r < 0)
return r;
- manager_network_read_link_servers(m);
+ (void) manager_network_read_link_servers(m);
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
diff --git a/src/timesync/timesyncd-manager.h b/src/timesync/timesyncd-manager.h
index 4d6258839b..d8d97cc1ee 100644
--- a/src/timesync/timesyncd-manager.h
+++ b/src/timesync/timesyncd-manager.h
@@ -1,25 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
- Copyright 2014 Kay Sievers, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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/timex.h>
+#include "sd-bus.h"
#include "sd-event.h"
#include "sd-network.h"
#include "sd-resolve.h"
@@ -27,6 +12,7 @@
#include "list.h"
#include "ratelimit.h"
#include "time-util.h"
+#include "timesyncd-ntp-message.h"
typedef struct Manager Manager;
@@ -40,6 +26,7 @@ typedef struct Manager Manager;
#define NTP_POLL_INTERVAL_MAX_USEC (2048 * USEC_PER_SEC)
struct Manager {
+ sd_bus *bus;
sd_event *event;
sd_resolve *resolve;
@@ -92,7 +79,7 @@ struct Manager {
/* last change */
bool jumped;
bool sync;
- int drift_ppm;
+ long drift_freq;
/* watch for time changes */
sd_event_source *event_clock_watch;
@@ -103,6 +90,11 @@ struct Manager {
/* RTC runs in local time, leave it alone */
bool rtc_local_time;
+
+ /* NTP response */
+ struct ntp_msg ntpmsg;
+ struct timespec origin_time, dest_time;
+ bool spike;
};
int manager_new(Manager **ret);
diff --git a/src/timesync/timesyncd-ntp-message.h b/src/timesync/timesyncd-ntp-message.h
new file mode 100644
index 0000000000..14fba6d2cc
--- /dev/null
+++ b/src/timesync/timesyncd-ntp-message.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sparse-endian.h"
+
+/* NTP protocol, packet header */
+#define NTP_LEAP_PLUSSEC 1
+#define NTP_LEAP_MINUSSEC 2
+#define NTP_LEAP_NOTINSYNC 3
+#define NTP_MODE_CLIENT 3
+#define NTP_MODE_SERVER 4
+#define NTP_FIELD_LEAP(f) (((f) >> 6) & 3)
+#define NTP_FIELD_VERSION(f) (((f) >> 3) & 7)
+#define NTP_FIELD_MODE(f) ((f) & 7)
+#define NTP_FIELD(l, v, m) (((l) << 6) | ((v) << 3) | (m))
+
+/*
+ * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
+ * in seconds relative to 0h on 1 January 1900."
+ */
+#define OFFSET_1900_1970 UINT64_C(2208988800)
+
+struct ntp_ts {
+ be32_t sec;
+ be32_t frac;
+} _packed_;
+
+struct ntp_ts_short {
+ be16_t sec;
+ be16_t frac;
+} _packed_;
+
+struct ntp_msg {
+ uint8_t field;
+ uint8_t stratum;
+ int8_t poll;
+ int8_t precision;
+ struct ntp_ts_short root_delay;
+ struct ntp_ts_short root_dispersion;
+ char refid[4];
+ struct ntp_ts reference_time;
+ struct ntp_ts origin_time;
+ struct ntp_ts recv_time;
+ struct ntp_ts trans_time;
+} _packed_;
diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c
index bd0030b982..aadecb6a1c 100644
--- a/src/timesync/timesyncd-server.c
+++ b/src/timesync/timesyncd-server.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Kay Sievers, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "timesyncd-server.h"
diff --git a/src/timesync/timesyncd-server.h b/src/timesync/timesyncd-server.h
index 2dc51a9730..8972706f20 100644
--- a/src/timesync/timesyncd-server.h
+++ b/src/timesync/timesyncd-server.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Kay Sievers, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "socket-util.h"
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c
index 3d7cfd5be5..987cded009 100644
--- a/src/timesync/timesyncd.c
+++ b/src/timesync/timesyncd.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Kay Sievers, Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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"
#include "sd-event.h"
@@ -29,10 +11,14 @@
#include "network-util.h"
#include "process-util.h"
#include "signal-util.h"
+#include "timesyncd-bus.h"
#include "timesyncd-conf.h"
#include "timesyncd-manager.h"
#include "user-util.h"
+#define STATE_DIR "/var/lib/systemd/timesync"
+#define CLOCK_FILE STATE_DIR "/clock"
+
static int load_clock_timestamp(uid_t uid, gid_t gid) {
_cleanup_close_ int fd = -1;
usec_t min = TIME_EPOCH * USEC_PER_SEC;
@@ -46,7 +32,7 @@ static int load_clock_timestamp(uid_t uid, gid_t gid) {
* systems lacking a battery backed RTC. We also will adjust
* the time to at least the build time of systemd. */
- fd = open("/var/lib/systemd/timesync/clock", O_RDWR|O_CLOEXEC, 0644);
+ fd = open(CLOCK_FILE, O_RDWR|O_CLOEXEC, 0644);
if (fd >= 0) {
struct stat st;
usec_t stamp;
@@ -62,23 +48,26 @@ static int load_clock_timestamp(uid_t uid, gid_t gid) {
if (geteuid() == 0) {
/* Try to fix the access mode, so that we can still
touch the file after dropping priviliges */
- r = fchmod(fd, 0644);
- if (r < 0)
- return log_error_errno(errno, "Failed to change file access mode: %m");
- r = fchown(fd, uid, gid);
+ r = fchmod_and_chown(fd, 0644, uid, gid);
if (r < 0)
- return log_error_errno(errno, "Failed to change file owner: %m");
+ log_warning_errno(r, "Failed to chmod or chown %s, ignoring: %m", CLOCK_FILE);
}
} else {
- r = mkdir_safe_label("/var/lib/systemd/timesync", 0755, uid, gid, true);
- if (r < 0)
- return log_error_errno(r, "Failed to create state directory: %m");
+ r = mkdir_safe_label(STATE_DIR, 0755, uid, gid,
+ MKDIR_FOLLOW_SYMLINK | MKDIR_WARN_MODE);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to create state directory, ignoring: %m");
+ goto settime;
+ }
/* create stamp file with the compiled-in date */
- (void) touch_file("/var/lib/systemd/timesync/clock", false, min, uid, gid, 0644);
+ r = touch_file(CLOCK_FILE, false, min, uid, gid, 0644);
+ if (r < 0)
+ log_debug_errno(r, "Failed to create %s, ignoring: %m", CLOCK_FILE);
}
+settime:
ct = now(CLOCK_REALTIME);
if (ct < min) {
struct timespec ts;
@@ -88,7 +77,7 @@ static int load_clock_timestamp(uid_t uid, gid_t gid) {
format_timestamp(date, sizeof(date), min));
if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, min)) < 0)
- log_error_errno(errno, "Failed to restore system clock: %m");
+ log_error_errno(errno, "Failed to restore system clock, ignoring: %m");
}
return 0;
@@ -145,6 +134,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ r = manager_connect_bus(m);
+ if (r < 0) {
+ log_error_errno(r, "Could not connect to bus: %m");
+ goto finish;
+ }
+
if (clock_is_localtime(NULL) > 0) {
log_info("The system is configured to read the RTC time in the local time zone. "
"This mode cannot be fully supported. All system time to RTC updates are disabled.");
@@ -179,8 +174,11 @@ int main(int argc, char *argv[]) {
}
/* if we got an authoritative time, store it in the file system */
- if (m->sync)
- (void) touch("/var/lib/systemd/timesync/clock");
+ if (m->sync) {
+ r = touch(CLOCK_FILE);
+ if (r < 0)
+ log_debug_errno(r, "Failed to touch %s, ignoring: %m", CLOCK_FILE);
+ }
sd_event_get_exit_code(m->event, &r);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 608cfbb58f..927de35f32 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1,23 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering, Kay Sievers
- Copyright 2015 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 <errno.h>
#include <fcntl.h>
@@ -61,6 +42,7 @@
#include "missing.h"
#include "mkdir.h"
#include "mount-util.h"
+#include "pager.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
@@ -73,6 +55,7 @@
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
#include "umask-util.h"
#include "user-util.h"
#include "util.h"
@@ -162,11 +145,13 @@ typedef enum DirectoryType {
_DIRECTORY_TYPE_MAX,
} DirectoryType;
+static bool arg_cat_config = false;
static bool arg_user = false;
static bool arg_create = false;
static bool arg_clean = false;
static bool arg_remove = false;
static bool arg_boot = false;
+static bool arg_no_pager = false;
static char **arg_include_prefixes = NULL;
static char **arg_exclude_prefixes = NULL;
@@ -190,10 +175,13 @@ static const Specifier specifier_table[] = {
{ 'U', specifier_user_id, NULL },
{ 'u', specifier_user_name, NULL },
{ 'h', specifier_user_home, NULL },
+
{ 't', specifier_directory, UINT_TO_PTR(DIRECTORY_RUNTIME) },
{ 'S', specifier_directory, UINT_TO_PTR(DIRECTORY_STATE) },
{ 'C', specifier_directory, UINT_TO_PTR(DIRECTORY_CACHE) },
{ 'L', specifier_directory, UINT_TO_PTR(DIRECTORY_LOGS) },
+ { 'T', specifier_tmp_dir, NULL },
+ { 'V', specifier_var_tmp_dir, NULL },
{}
};
@@ -310,8 +298,7 @@ static int user_config_paths(char*** ret) {
if (r < 0)
return r;
- *ret = res;
- res = NULL;
+ *ret = TAKE_PTR(res);
return 0;
}
@@ -440,7 +427,7 @@ static void load_unix_sockets(void) {
goto fail;
}
- path_kill_slashes(s);
+ path_simplify(s, false);
r = set_consume(unix_sockets, s);
if (r < 0 && r != -EEXIST) {
@@ -822,15 +809,9 @@ static int fd_set_perms(Item *i, int fd, const struct stat *st) {
if (m == (st->st_mode & 07777))
log_debug("\"%s\" has correct mode %o already.", path, st->st_mode);
else {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
-
log_debug("Changing \"%s\" to mode %o.", path, m);
-
- /* fchmodat() still doesn't have AT_EMPTY_PATH flag. */
- xsprintf(procfs_path, "/proc/self/fd/%i", fd);
-
- if (chmod(procfs_path, m) < 0)
- return log_error_errno(errno, "chmod() of %s via %s failed: %m", path, procfs_path);
+ if (fchmod_opath(fd, m) < 0)
+ return log_error_errno(errno, "fchmod() of %s failed: %m", path);
}
}
}
@@ -851,7 +832,7 @@ static int fd_set_perms(Item *i, int fd, const struct stat *st) {
}
shortcut:
- return label_fix(path, false, false);
+ return label_fix(path, 0);
}
static int path_set_perms(Item *i, const char *path) {
@@ -924,7 +905,7 @@ static int parse_xattrs_from_arg(Item *i) {
}
static int fd_set_xattrs(Item *i, int fd, const struct stat *st) {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *path = NULL;
char **name, **value;
int r;
@@ -1028,7 +1009,7 @@ static int path_set_acl(const char *path, const char *pretty, acl_type_t type, a
static int fd_set_acls(Item *item, int fd, const struct stat *st) {
int r = 0;
#if HAVE_ACL
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *path = NULL;
assert(item);
@@ -1190,7 +1171,6 @@ static int parse_attribute_from_arg(Item *item) {
}
static int fd_set_attribute(Item *item, int fd, const struct stat *st) {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
_cleanup_close_ int procfs_fd = -1;
_cleanup_free_ char *path = NULL;
unsigned f;
@@ -1217,9 +1197,7 @@ static int fd_set_attribute(Item *item, int fd, const struct stat *st) {
if (!S_ISDIR(st->st_mode))
f &= ~FS_DIRSYNC_FL;
- xsprintf(procfs_path, "/proc/self/fd/%i", fd);
-
- procfs_fd = open(procfs_path, O_RDONLY|O_CLOEXEC|O_NOATIME);
+ procfs_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NOATIME);
if (procfs_fd < 0)
return -errno;
@@ -1263,7 +1241,7 @@ static int write_one_file(Item *i, const char *path) {
RUN_WITH_UMASK(0000) {
mac_selinux_create_file_prepare(path, S_IFREG);
- fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
+ fd = open(path, flags|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
mac_selinux_create_file_clear();
}
@@ -1328,7 +1306,7 @@ static int item_do(Item *i, int fd, const struct stat *st, fdaction_t action) {
r = action(i, fd, st);
if (S_ISDIR(st->st_mode)) {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
@@ -1471,8 +1449,7 @@ static int create_item(Item *i) {
return r;
break;
- case COPY_FILES: {
-
+ case COPY_FILES:
RUN_WITH_UMASK(0000)
(void) mkdir_parents_label(i->path, 0755);
@@ -1526,7 +1503,7 @@ static int create_item(Item *i) {
if (IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) {
- if (btrfs_is_subvol(isempty(arg_root) ? "/" : arg_root) <= 0)
+ if (btrfs_is_subvol(empty_to_root(arg_root)) <= 0)
/* Don't create a subvolume unless the
* root directory is one, too. We do
@@ -1645,7 +1622,6 @@ static int create_item(Item *i) {
return r;
break;
- }
case CREATE_SYMLINK: {
RUN_WITH_UMASK(0000)
@@ -2138,6 +2114,43 @@ static int specifier_expansion_from_arg(Item *i) {
return 0;
}
+static int patch_var_run(const char *fname, unsigned line, char **path) {
+ const char *k;
+ char *n;
+
+ assert(path);
+ assert(*path);
+
+ /* Optionally rewrites lines referencing /var/run/, to use /run/ instead. Why bother? tmpfiles merges lines in
+ * some cases and detects conflicts in others. If files/directories are specified through two equivalent lines
+ * this is problematic as neither case will be detected. Ideally we'd detect these cases by resolving symlinks
+ * early, but that's precisely not what we can do here as this code very likely is running very early on, at a
+ * time where the paths in question are not available yet, or even more importantly, our own tmpfiles rules
+ * might create the paths that are intermediary to the listed paths. We can't really cover the generic case,
+ * but the least we can do is cover the specific case of /var/run vs. /run, as /var/run is a legacy name for
+ * /run only, and we explicitly document that and require that on systemd systems the former is a symlink to
+ * the latter. Moreover files below this path are by far the primary usecase for tmpfiles.d/. */
+
+ k = path_startswith(*path, "/var/run/");
+ if (isempty(k)) /* Don't complain about other paths than /var/run, and not about /var/run itself either. */
+ return 0;
+
+ n = strjoin("/run/", k);
+ if (!n)
+ return log_oom();
+
+ /* Also log about this briefly. We do so at LOG_NOTICE level, as we fixed up the situation automatically, hence
+ * there's no immediate need for action by the user. However, in the interest of making things less confusing
+ * to the user, let's still inform the user that these snippets should really be updated. */
+
+ log_notice("[%s:%u] Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", fname, line, *path, n);
+
+ free(*path);
+ *path = n;
+
+ return 0;
+}
+
static int parse_line(const char *fname, unsigned line, const char *buffer, bool *invalid_config) {
_cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
@@ -2167,9 +2180,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
/* invalid quoting and such or an unknown specifier */
*invalid_config = true;
return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
- }
-
- else if (r < 2) {
+ } else if (r < 2) {
*invalid_config = true;
log_error("[%s:%u] Syntax error.", fname, line);
return -EIO;
@@ -2218,6 +2229,10 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, path);
}
+ r = patch_var_run(fname, line, &i.path);
+ if (r < 0)
+ return r;
+
switch (i.type) {
case CREATE_DIRECTORY:
@@ -2270,7 +2285,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
return -EBADMSG;
}
- path_kill_slashes(i.argument);
+ path_simplify(i.argument, false);
break;
case CREATE_CHAR_DEVICE:
@@ -2343,7 +2358,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
return -EBADMSG;
}
- path_kill_slashes(i.path);
+ path_simplify(i.path, false);
if (!should_include_path(i.path))
return 0;
@@ -2466,12 +2481,24 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool
return 0;
}
+static int cat_config(char **config_dirs, char **args) {
+ _cleanup_strv_free_ char **files = NULL;
+ int r;
+
+ r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, NULL);
+ if (r < 0)
+ return r;
+
+ return cat_files(NULL, files, 0);
+}
+
static void 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"
" --user Execute user configuration\n"
" --version Show package version\n"
+ " --cat-config Show configuration files\n"
" --create Create marked files/directories\n"
" --clean Clean up marked directories\n"
" --remove Remove marked files/directories\n"
@@ -2480,6 +2507,7 @@ static void help(void) {
" --exclude-prefix=PATH Ignore rules with the specified prefix\n"
" --root=PATH Operate on an alternate filesystem root\n"
" --replace=PATH Treat arguments as replacement for PATH\n"
+ " --no-pager Do not pipe output into a pager\n"
, program_invocation_short_name);
}
@@ -2487,6 +2515,7 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
+ ARG_CAT_CONFIG,
ARG_USER,
ARG_CREATE,
ARG_CLEAN,
@@ -2496,12 +2525,14 @@ static int parse_argv(int argc, char *argv[]) {
ARG_EXCLUDE_PREFIX,
ARG_ROOT,
ARG_REPLACE,
+ ARG_NO_PAGER,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "user", no_argument, NULL, ARG_USER },
{ "version", no_argument, NULL, ARG_VERSION },
+ { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
{ "create", no_argument, NULL, ARG_CREATE },
{ "clean", no_argument, NULL, ARG_CLEAN },
{ "remove", no_argument, NULL, ARG_REMOVE },
@@ -2510,6 +2541,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
{ "root", required_argument, NULL, ARG_ROOT },
{ "replace", required_argument, NULL, ARG_REPLACE },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
@@ -2529,6 +2561,10 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_VERSION:
return version();
+ case ARG_CAT_CONFIG:
+ arg_cat_config = true;
+ break;
+
case ARG_USER:
arg_user = true;
break;
@@ -2575,6 +2611,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_replace = optarg;
break;
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
case '?':
return -EINVAL;
@@ -2582,11 +2622,16 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached("Unhandled option");
}
- if (!arg_clean && !arg_create && !arg_remove) {
+ if (!arg_clean && !arg_create && !arg_remove && !arg_cat_config) {
log_error("You need to specify at least one of --clean, --create or --remove.");
return -EINVAL;
}
+ if (arg_replace && arg_cat_config) {
+ log_error("Option --replace= is not supported with --cat-config");
+ return -EINVAL;
+ }
+
if (arg_replace && optind >= argc) {
log_error("When --replace= is given, some configuration items must be specified");
return -EINVAL;
@@ -2702,19 +2747,9 @@ static int read_config_files(char **config_dirs, char **args, bool *invalid_conf
char **f;
int r;
- r = conf_files_list_strv(&files, ".conf", arg_root, 0, (const char* const*) config_dirs);
+ r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, &p);
if (r < 0)
- return log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
-
- if (arg_replace) {
- r = conf_files_insert(&files, arg_root, config_dirs, arg_replace);
- if (r < 0)
- return log_error_errno(r, "Failed to extend tmpfiles.d file list: %m");
-
- p = path_join(arg_root, arg_replace, NULL);
- if (!p)
- return log_oom();
- }
+ return r;
STRV_FOREACH(f, files)
if (p && path_equal(*f, p)) {
@@ -2746,20 +2781,6 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- umask(0022);
-
- mac_selinux_init();
-
- items = ordered_hashmap_new(&string_hash_ops);
- globs = ordered_hashmap_new(&string_hash_ops);
-
- if (!items || !globs) {
- r = log_oom();
- goto finish;
- }
-
- r = 0;
-
if (arg_user) {
r = user_config_paths(&config_dirs);
if (r < 0) {
@@ -2782,6 +2803,25 @@ int main(int argc, char *argv[]) {
log_debug("Looking for configuration files in (higher priority first):\n\t%s", t);
}
+ if (arg_cat_config) {
+ (void) pager_open(arg_no_pager, false);
+
+ r = cat_config(config_dirs, argv + optind);
+ goto finish;
+ }
+
+ umask(0022);
+
+ mac_selinux_init();
+
+ items = ordered_hashmap_new(&string_hash_ops);
+ globs = ordered_hashmap_new(&string_hash_ops);
+
+ if (!items || !globs) {
+ r = log_oom();
+ goto finish;
+ }
+
/* If command line arguments are specified along with --replace, read all
* configuration files and insert the positional arguments at the specified
* place. Otherwise, if command line arguments are specified, execute just
@@ -2812,6 +2852,8 @@ int main(int argc, char *argv[]) {
}
finish:
+ pager_close();
+
ordered_hashmap_free_with_destructor(items, item_array_free);
ordered_hashmap_free_with_destructor(globs, item_array_free);
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 74a10bb175..40d594896b 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2015 Werner Fink
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2015 Werner Fink
***/
#include <errno.h>
diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c
index 7e3654c30f..e077a699a4 100644
--- a/src/udev/ata_id/ata_id.c
+++ b/src/udev/ata_id/ata_id.c
@@ -2,22 +2,8 @@
/*
* ata_id - reads product/serial number from ATA drives
*
- * Copyright (C) 2005-2008 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2009 Lennart Poettering <lennart@poettering.net>
- * Copyright (C) 2009-2010 David Zeuthen <zeuthen@gmail.com>
+ * Copyright © 2009-2010 David Zeuthen <zeuthen@gmail.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
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
@@ -318,7 +304,7 @@ static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offs
* device represented by @fd. If successful, then the result will be
* copied into @out_identify and @out_is_packet_device.
*
- * This routine is based on code from libatasmart, Copyright 2008
+ * This routine is based on code from libatasmart, Copyright © 2008
* Lennart Poettering, LGPL v2.1.
*
* Returns: 0 if the data was successfully obtained, otherwise
@@ -405,9 +391,8 @@ out:
return ret;
}
-int main(int argc, char *argv[])
-{
- _cleanup_udev_unref_ struct udev *udev = NULL;
+int main(int argc, char *argv[]) {
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
struct hd_driveid id;
union {
uint8_t byte[512];
diff --git a/src/udev/cdrom_id/cdrom_id.c b/src/udev/cdrom_id/cdrom_id.c
index 5e7bebeb16..1aaa263f76 100644
--- a/src/udev/cdrom_id/cdrom_id.c
+++ b/src/udev/cdrom_id/cdrom_id.c
@@ -2,20 +2,7 @@
/*
* cdrom_id - optical drive and media information prober
*
- * Copyright (C) 2008-2010 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
diff --git a/src/udev/collect/collect.c b/src/udev/collect/collect.c
index c8fa47b3d7..a88dedd002 100644
--- a/src/udev/collect/collect.c
+++ b/src/udev/collect/collect.c
@@ -11,7 +11,7 @@
* number of missing IDs otherwise.
* A negative number is returned on error.
*
- * Copyright(C) 2007, Hannes Reinecke <hare@suse.de>
+ * Copyright © 2007, Hannes Reinecke <hare@suse.de>
*
* 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
diff --git a/src/udev/meson.build b/src/udev/meson.build
index de2fd2d9c4..3bcd2bd3d7 100644
--- a/src/udev/meson.build
+++ b/src/udev/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
udevadm_sources = files('''
udevadm.c
@@ -63,7 +48,7 @@ endif
if conf.get('HAVE_ACL') == 1
libudev_core_sources += ['udev-builtin-uaccess.c',
- logind_acl_c,
+ logind_acl_c,
sd_login_c]
endif
@@ -124,12 +109,29 @@ libudev_basic = static_library(
c_args : ['-fvisibility=default'])
libudev_static = static_library(
- 'udev',
+ 'udev_static',
'udev.h',
include_directories : includes,
link_with : udev_link_with,
link_whole : libudev_basic)
+static_libudev = get_option('static-libudev')
+static_libudev_pic = static_libudev == 'true' or static_libudev == 'pic'
+install_libudev_static = static_library(
+ 'udev',
+ basic_sources,
+ shared_sources,
+ libsystemd_sources,
+ libudev_sources,
+ include_directories : includes,
+ build_by_default : static_libudev != 'false',
+ install : static_libudev != 'false',
+ install_dir : rootlibdir,
+ link_depends : libudev_sym,
+ dependencies : libshared_deps + [libmount],
+ c_args : static_libudev_pic ? [] : ['-fno-PIC'],
+ pic : static_libudev_pic)
+
libudev = shared_library(
'udev',
'udev.h', # pick a header file at random to work around old meson bug
diff --git a/src/udev/mtd_probe/mtd_probe.c b/src/udev/mtd_probe/mtd_probe.c
index 1d692f1187..f47b13378c 100644
--- a/src/udev/mtd_probe/mtd_probe.c
+++ b/src/udev/mtd_probe/mtd_probe.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2010 - Maxim Levitsky
+ * Copyright © 2010 - Maxim Levitsky
*
* mtd_probe is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
* Boston, MA 02110-1301 USA
*/
+#include <errno.h>
#include <fcntl.h>
#include <mtd/mtd-user.h>
#include <stdio.h>
@@ -27,31 +28,32 @@
#include <sys/types.h>
#include <unistd.h>
+#include "alloc-util.h"
+#include "fd-util.h"
#include "mtd_probe.h"
-int main(int argc, char** argv)
-{
- int mtd_fd;
- int error;
+int main(int argc, char** argv) {
+ _cleanup_close_ int mtd_fd = -1;
mtd_info_t mtd_info;
if (argc != 2) {
printf("usage: mtd_probe /dev/mtd[n]\n");
- return 1;
+ return EXIT_FAILURE;
}
mtd_fd = open(argv[1], O_RDONLY|O_CLOEXEC);
- if (mtd_fd == -1) {
- perror("open");
- exit(-1);
+ if (mtd_fd < 0) {
+ log_error_errno(errno, "Failed to open: %m");
+ return EXIT_FAILURE;
}
- error = ioctl(mtd_fd, MEMGETINFO, &mtd_info);
- if (error == -1) {
- perror("ioctl");
- exit(-1);
+ if (ioctl(mtd_fd, MEMGETINFO, &mtd_info) < 0) {
+ log_error_errno(errno, "Failed to issue MEMGETINFO ioctl: %m");
+ return EXIT_FAILURE;
}
- probe_smart_media(mtd_fd, &mtd_info);
- return -1;
+ if (probe_smart_media(mtd_fd, &mtd_info) < 0)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
}
diff --git a/src/udev/mtd_probe/mtd_probe.h b/src/udev/mtd_probe/mtd_probe.h
index 39841f9b7d..1d8c93b7fd 100644
--- a/src/udev/mtd_probe/mtd_probe.h
+++ b/src/udev/mtd_probe/mtd_probe.h
@@ -2,7 +2,7 @@
#pragma once
/*
- * Copyright (C) 2010 - Maxim Levitsky
+ * Copyright © 2010 - Maxim Levitsky
*
* mtd_probe is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -49,4 +49,4 @@ struct sm_oob {
#define SM_SMALL_PAGE 256
#define SM_SMALL_OOB_SIZE 8
-void probe_smart_media(int mtd_fd, mtd_info_t *info);
+int probe_smart_media(int mtd_fd, mtd_info_t *info);
diff --git a/src/udev/mtd_probe/probe_smartmedia.c b/src/udev/mtd_probe/probe_smartmedia.c
index 5d58de6a87..099809da1b 100644
--- a/src/udev/mtd_probe/probe_smartmedia.c
+++ b/src/udev/mtd_probe/probe_smartmedia.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2010 - Maxim Levitsky
+ * Copyright © 2010 - Maxim Levitsky
*
* mtd_probe is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
* Boston, MA 02110-1301 USA
*/
+#include <errno.h>
#include <fcntl.h>
#include <mtd/mtd-user.h>
#include <stdint.h>
@@ -35,8 +36,7 @@ static const uint8_t cis_signature[] = {
0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20
};
-
-void probe_smart_media(int mtd_fd, mtd_info_t* info) {
+int probe_smart_media(int mtd_fd, mtd_info_t* info) {
int sector_size;
int block_size;
int size_in_megs;
@@ -47,17 +47,21 @@ void probe_smart_media(int mtd_fd, mtd_info_t* info) {
cis_buffer = malloc(SM_SECTOR_SIZE);
if (!cis_buffer)
- return;
+ return log_oom();
- if (info->type != MTD_NANDFLASH)
- goto exit;
+ if (info->type != MTD_NANDFLASH) {
+ log_debug("Not marked MTD_NANDFLASH.");
+ return -EINVAL;
+ }
sector_size = info->writesize;
block_size = info->erasesize;
size_in_megs = info->size / (1024 * 1024);
- if (!IN_SET(sector_size, SM_SECTOR_SIZE, SM_SMALL_PAGE))
- goto exit;
+ if (!IN_SET(sector_size, SM_SECTOR_SIZE, SM_SMALL_PAGE)) {
+ log_debug("Unexpected sector size: %i", sector_size);
+ return -EINVAL;
+ }
switch(size_in_megs) {
case 1:
@@ -72,26 +76,26 @@ void probe_smart_media(int mtd_fd, mtd_info_t* info) {
break;
}
- for (offset = 0 ; offset < block_size * spare_count ;
- offset += sector_size) {
- lseek(mtd_fd, SEEK_SET, offset);
+ for (offset = 0; offset < block_size * spare_count; offset += sector_size) {
+ (void) lseek(mtd_fd, SEEK_SET, offset);
+
if (read(mtd_fd, cis_buffer, SM_SECTOR_SIZE) == SM_SECTOR_SIZE) {
cis_found = 1;
break;
}
}
- if (!cis_found)
- goto exit;
+ if (!cis_found) {
+ log_debug("CIS not found");
+ return -EINVAL;
+ }
if (memcmp(cis_buffer, cis_signature, sizeof(cis_signature)) != 0 &&
- (memcmp(cis_buffer + SM_SMALL_PAGE, cis_signature,
- sizeof(cis_signature)) != 0))
- goto exit;
+ memcmp(cis_buffer + SM_SMALL_PAGE, cis_signature, sizeof(cis_signature)) != 0) {
+ log_debug("CIS signature didn't match");
+ return -EINVAL;
+ }
printf("MTD_FTL=smartmedia\n");
- exit(EXIT_SUCCESS);
-
-exit:
- return;
+ return 0;
}
diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c
index 8179a5e2f8..4bb4216ac8 100644
--- a/src/udev/net/ethtool-util.c
+++ b/src/udev/net/ethtool-util.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <net/if.h>
#include <sys/ioctl.h>
@@ -72,7 +54,6 @@ static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {
[NET_DEV_FEAT_LRO] = "rx-lro",
[NET_DEV_FEAT_TSO] = "tx-tcp-segmentation",
[NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation",
- [NET_DEV_FEAT_UFO] = "tx-udp-fragmentation",
};
int ethtool_connect(int *ret) {
@@ -305,8 +286,7 @@ static int get_stringset(int fd, struct ifreq *ifr, int stringset_id, struct eth
if (r < 0)
return -errno;
- *gstrings = strings;
- strings = NULL;
+ *gstrings = TAKE_PTR(strings);
return 0;
}
@@ -583,3 +563,105 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *l
return r;
}
+
+int config_parse_channel(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ link_config *config = data;
+ uint32_t k;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou32(rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse channel value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (k < 1) {
+ log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid %s value, ignoring: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ if (streq(lvalue, "RxChannels")) {
+ config->channels.rx_count = k;
+ config->channels.rx_count_set = true;
+ } else if (streq(lvalue, "TxChannels")) {
+ config->channels.tx_count = k;
+ config->channels.tx_count_set = true;
+ } else if (streq(lvalue, "OtherChannels")) {
+ config->channels.other_count = k;
+ config->channels.other_count_set = true;
+ } else if (streq(lvalue, "CombinedChannels")) {
+ config->channels.combined_count = k;
+ config->channels.combined_count_set = true;
+ }
+
+ return 0;
+}
+
+int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels) {
+ struct ethtool_channels ecmd = {
+ .cmd = ETHTOOL_GCHANNELS
+ };
+ struct ifreq ifr = {
+ .ifr_data = (void*) &ecmd
+ };
+
+ bool need_update = false;
+ int r;
+
+ if (*fd < 0) {
+ r = ethtool_connect(fd);
+ if (r < 0)
+ return log_warning_errno(r, "link_config: could not connect to ethtool: %m");
+ }
+
+ strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
+
+ r = ioctl(*fd, SIOCETHTOOL, &ifr);
+ if (r < 0)
+ return -errno;
+
+ if (channels->rx_count_set && ecmd.rx_count != channels->rx_count) {
+ ecmd.rx_count = channels->rx_count;
+ need_update = true;
+ }
+
+ if (channels->tx_count_set && ecmd.tx_count != channels->tx_count) {
+ ecmd.tx_count = channels->tx_count;
+ need_update = true;
+ }
+
+ if (channels->other_count_set && ecmd.other_count != channels->other_count) {
+ ecmd.other_count = channels->other_count;
+ need_update = true;
+ }
+
+ if (channels->combined_count_set && ecmd.combined_count != channels->combined_count) {
+ ecmd.combined_count = channels->combined_count;
+ need_update = true;
+ }
+
+ if (need_update) {
+ ecmd.cmd = ETHTOOL_SCHANNELS;
+
+ r = ioctl(*fd, SIOCETHTOOL, &ifr);
+ if (r < 0)
+ return -errno;
+ }
+
+ return 0;
+}
diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h
index 5681472a9a..064bf4d2bd 100644
--- a/src/udev/net/ethtool-util.h
+++ b/src/udev/net/ethtool-util.h
@@ -1,24 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <macro.h>
#include <linux/ethtool.h>
@@ -55,7 +37,6 @@ typedef enum NetDevFeature {
NET_DEV_FEAT_LRO,
NET_DEV_FEAT_TSO,
NET_DEV_FEAT_TSO6,
- NET_DEV_FEAT_UFO,
_NET_DEV_FEAT_MAX,
_NET_DEV_FEAT_INVALID = -1
} NetDevFeature;
@@ -86,6 +67,18 @@ struct ethtool_link_usettings {
} link_modes;
};
+typedef struct netdev_channels {
+ uint32_t rx_count;
+ uint32_t tx_count;
+ uint32_t other_count;
+ uint32_t combined_count;
+
+ bool rx_count_set;
+ bool tx_count_set;
+ bool other_count_set;
+ bool combined_count_set;
+} netdev_channels;
+
int ethtool_connect(int *ret);
int ethtool_get_driver(int *fd, const char *ifname, char **ret);
@@ -93,6 +86,7 @@ int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex du
int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol);
int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features);
int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *link);
+int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels);
const char *duplex_to_string(Duplex d) _const_;
Duplex duplex_from_string(const char *d) _pure_;
@@ -106,3 +100,4 @@ NetDevPort port_from_string(const char *port) _pure_;
int config_parse_duplex(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_wol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_channel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf
index 5cb126d870..5640fa0513 100644
--- a/src/udev/net/link-config-gperf.gperf
+++ b/src/udev/net/link-config-gperf.gperf
@@ -4,9 +4,9 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#endif
#include <stddef.h>
#include "conf-parser.h"
-#include "network-internal.h"
-#include "link-config.h"
#include "ethtool-util.h"
+#include "link-config.h"
+#include "network-internal.h"
%}
struct ConfigPerfItem;
%null_strings
@@ -19,7 +19,7 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Match.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, match_mac)
+Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name)
Match.Path, config_parse_strv, 0, offsetof(link_config, match_path)
Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver)
@@ -35,7 +35,7 @@ Link.MACAddress, config_parse_hwaddr, 0,
Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy)
Link.Name, config_parse_ifname, 0, offsetof(link_config, name)
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
-Link.MTUBytes, config_parse_iec_size, 0, offsetof(link_config, mtu)
+Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed)
Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)
Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation)
@@ -44,6 +44,10 @@ Link.Port, config_parse_port, 0,
Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO])
Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO])
Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO6])
-Link.UDPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_UFO])
+Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0
Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GRO])
Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_LRO])
+Link.RxChannels, config_parse_channel, 0, 0
+Link.TxChannels, config_parse_channel, 0, 0
+Link.OtherChannels, config_parse_channel, 0, 0
+Link.CombinedChannels, config_parse_channel, 0, 0
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index a4368f088d..cec4f4f779 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <netinet/ether.h>
@@ -70,7 +52,7 @@ static void link_config_free(link_config *link) {
free(link->filename);
- free(link->match_mac);
+ set_free_free(link->match_mac);
strv_free(link->match_path);
strv_free(link->match_driver);
strv_free(link->match_type);
@@ -135,8 +117,7 @@ int link_config_ctx_new(link_config_ctx **ret) {
ctx->enable_name_policy = true;
- *ret = ctx;
- ctx = NULL;
+ *ret = TAKE_PTR(ctx);
return 0;
}
@@ -183,7 +164,7 @@ static int load_link(link_config_ctx *ctx, const char *filename) {
else
log_debug("Parsed configuration file %s", filename);
- if (link->mtu > UINT_MAX || link->speed > UINT_MAX)
+ if (link->speed > UINT_MAX)
return -ERANGE;
link->filename = strdup(filename);
@@ -407,6 +388,12 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
if (r < 0)
log_warning_errno(r, "Could not set offload features of %s: %m", old_name);
+ if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) {
+ r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels);
+ if (r < 0)
+ log_warning_errno(r, "Could not set channels of %s: %m", old_name);
+ }
+
ifindex = udev_device_get_ifindex(device);
if (ifindex <= 0) {
log_warning("Could not find ifindex");
@@ -480,7 +467,7 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu);
if (r < 0)
- return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name);
+ return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name);
*name = new_name;
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index dabc3eff8f..4798bb101c 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -1,30 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "condition.h"
#include "ethtool-util.h"
#include "list.h"
+#include "set.h"
typedef struct link_config_ctx link_config_ctx;
typedef struct link_config link_config;
@@ -51,7 +34,7 @@ typedef enum NamePolicy {
struct link_config {
char *filename;
- struct ether_addr *match_mac;
+ Set *match_mac;
char **match_path;
char **match_driver;
char **match_type;
@@ -68,13 +51,14 @@ struct link_config {
NamePolicy *name_policy;
char *name;
char *alias;
- size_t mtu;
+ uint32_t mtu;
size_t speed;
Duplex duplex;
int autonegotiation;
WakeOnLan wol;
NetDevPort port;
NetDevFeature features[_NET_DEV_FEAT_MAX];
+ netdev_channels channels;
LIST_FIELDS(link_config, links);
};
diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c
index 32c1a8def4..5caab7774f 100644
--- a/src/udev/scsi_id/scsi_id.c
+++ b/src/udev/scsi_id/scsi_id.c
@@ -1,20 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) IBM Corp. 2003
- * Copyright (C) SUSE Linux Products GmbH, 2006
+ * Copyright © IBM Corp. 2003
+ * Copyright © SUSE Linux Products GmbH, 2006
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
@@ -164,7 +152,7 @@ static int get_file_options(struct udev *udev,
const char *vendor, const char *model,
int *argc, char ***newargv)
{
- char *buffer;
+ _cleanup_free_ char *buffer = NULL;
_cleanup_fclose_ FILE *f;
char *buf;
char *str1;
@@ -259,9 +247,8 @@ static int get_file_options(struct udev *udev,
if (vendor_in == NULL)
break;
} else if (vendor_in &&
- strneq(vendor, vendor_in, strlen(vendor_in)) &&
- (!model_in ||
- (strneq(model, model_in, strlen(model_in))))) {
+ startswith(vendor, vendor_in) &&
+ (!model_in || startswith(model, model_in))) {
/*
* Matched vendor and optionally model.
*
@@ -296,14 +283,13 @@ static int get_file_options(struct udev *udev,
(*newargv)[c] = buffer;
for (c = 1; c < *argc; c++)
(*newargv)[c] = strsep(&buffer, " \t");
+ buffer = NULL;
}
} else {
/* No matches */
retval = 1;
}
}
- if (retval != 0)
- free(buffer);
return retval;
}
@@ -570,9 +556,8 @@ out:
return retval;
}
-int main(int argc, char **argv)
-{
- _cleanup_udev_unref_ struct udev *udev;
+int main(int argc, char **argv) {
+ _cleanup_(udev_unrefp) struct udev *udev;
int retval = 0;
char maj_min_dev[MAX_PATH_LEN];
int newargc;
diff --git a/src/udev/scsi_id/scsi_id.h b/src/udev/scsi_id/scsi_id.h
index 9a33f6a158..1222f250ec 100644
--- a/src/udev/scsi_id/scsi_id.h
+++ b/src/udev/scsi_id/scsi_id.h
@@ -2,20 +2,8 @@
#pragma once
/*
- * Copyright (C) IBM Corp. 2003
+ * Copyright © IBM Corp. 2003
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define MAX_PATH_LEN 512
diff --git a/src/udev/scsi_id/scsi_serial.c b/src/udev/scsi_id/scsi_serial.c
index bf6b28e8e5..fd91657a32 100644
--- a/src/udev/scsi_id/scsi_serial.c
+++ b/src/udev/scsi_id/scsi_serial.c
@@ -1,21 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) IBM Corp. 2003
+ * Copyright © IBM Corp. 2003
*
* Author: Patrick Mansfield<patmans@us.ibm.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
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -590,7 +578,7 @@ static int check_fill_0x83_prespc3(struct udev *udev,
{
int i, j;
- serial[0] = hex_str[id_search->id_type];
+ serial[0] = hex_str[SCSI_ID_NAA];
/* serial has been memset to zero before */
j = strlen(serial); /* j = 1; */
@@ -603,7 +591,6 @@ static int check_fill_0x83_prespc3(struct udev *udev,
return 0;
}
-
/* Get device identification VPD page */
static int do_scsi_page83_inquiry(struct udev *udev,
struct scsi_id_device *dev_scsi, int fd,
@@ -739,7 +726,7 @@ static int do_scsi_page83_prespc3_inquiry(struct udev *udev,
if (page_83[6] == 0)
return 2;
- serial[0] = hex_str[id_search_list[0].id_type];
+ serial[0] = hex_str[SCSI_ID_NAA];
/*
* The first four bytes contain data, not a descriptor.
*/
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index eeed803f57..477b7ef61f 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -2,21 +2,8 @@
/*
* probe disks for filesystems and partitions
*
- * Copyright (C) 2011 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
+ * Copyright © 2011 Karel Zak <kzak@redhat.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
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <blkid.h>
@@ -228,7 +215,7 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t
int64_t offset = 0;
bool noraid = false;
_cleanup_close_ int fd = -1;
- _cleanup_blkid_free_probe_ blkid_probe pr = NULL;
+ _cleanup_(blkid_free_probep) blkid_probe pr = NULL;
const char *data;
const char *name;
int nvals;
diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c
index 9e0f1e0aac..2e8535598d 100644
--- a/src/udev/udev-builtin-btrfs.c
+++ b/src/udev/udev-builtin-btrfs.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fcntl.h>
#include <stdlib.h>
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index dbfe024298..396384f6c8 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <fnmatch.h>
#include <getopt.h>
@@ -73,9 +55,9 @@ static const char *modalias_usb(struct udev_device *dev, char *s, size_t size) {
if (!p)
return NULL;
if (safe_atoux16(v, &vn) < 0)
- return NULL;
+ return NULL;
if (safe_atoux16(p, &pn) < 0)
- return NULL;
+ return NULL;
snprintf(s, size, "usb:v%04Xp%04X*", vn, pn);
return s;
}
@@ -139,7 +121,7 @@ static int builtin_hwdb(struct udev_device *dev, int argc, char *argv[], bool te
const char *device = NULL;
const char *subsystem = NULL;
const char *prefix = NULL;
- _cleanup_udev_device_unref_ struct udev_device *srcdev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *srcdev = NULL;
if (!hwdb)
return EXIT_FAILURE;
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 4d5b1233f1..680170028b 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -2,24 +2,10 @@
/*
* expose input properties via udev
*
- * Copyright (C) 2009 Martin Pitt <martin.pitt@ubuntu.com>
- * Portions Copyright (C) 2004 David Zeuthen, <david@fubar.dk>
- * Copyright (C) 2011 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org>
- * Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright © 2009 Martin Pitt <martin.pitt@ubuntu.com>
+ * Portions Copyright © 2004 David Zeuthen, <david@fubar.dk>
+ * Copyright © 2014 Carlos Garnacho <carlosg@gnome.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -307,7 +293,7 @@ static bool test_key(struct udev_device *dev,
/* the first 32 bits are ESC, numbers, and Q to D; if we have all of
* those, consider it a full keyboard; do not test KEY_RESERVED, though */
mask = 0xFFFFFFFE;
- if ((bitmask_key[0] & mask) == mask) {
+ if (FLAGS_SET(bitmask_key[0], mask)) {
udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1");
ret = true;
}
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index 0044280399..9160a5b5d5 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- 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 <stdlib.h>
diff --git a/src/udev/udev-builtin-kmod.c b/src/udev/udev-builtin-kmod.c
index 2530fdfd23..e24e8e55e2 100644
--- a/src/udev/udev-builtin-kmod.c
+++ b/src/udev/udev-builtin-kmod.c
@@ -2,21 +2,8 @@
/*
* load kernel modules
*
- * Copyright (C) 2011-2012 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2011 ProFUSION embedded systems
+ * Copyright © 2011 ProFUSION embedded systems
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 6efa712930..147e04ab8c 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
/*
* Predictable network interface device names based on:
@@ -112,6 +94,8 @@
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
+#include "parse-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "udev.h"
@@ -149,6 +133,11 @@ struct netnames {
char platform_path[IFNAMSIZ];
};
+struct virtfn_info {
+ struct udev_device *physfn_pcidev;
+ char suffix[IFNAMSIZ];
+};
+
/* skip intermediate virtio devices */
static struct udev_device *skip_virtio(struct udev_device *dev) {
struct udev_device *parent = dev;
@@ -161,6 +150,67 @@ static struct udev_device *skip_virtio(struct udev_device *dev) {
return parent;
}
+static int get_virtfn_info(struct udev_device *dev, struct netnames *names, struct virtfn_info *vf_info) {
+ struct udev *udev;
+ const char *physfn_link_file;
+ _cleanup_free_ char *physfn_pci_syspath = NULL;
+ _cleanup_free_ char *virtfn_pci_syspath = NULL;
+ struct dirent *dent;
+ _cleanup_closedir_ DIR *dir = NULL;
+ struct virtfn_info vf_info_local = {};
+ int r;
+
+ udev = udev_device_get_udev(names->pcidev);
+ if (!udev)
+ return -ENOENT;
+ /* Check if this is a virtual function. */
+ physfn_link_file = strjoina(udev_device_get_syspath(names->pcidev), "/physfn");
+ r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath);
+ if (r < 0)
+ return r;
+
+ /* Get physical function's pci device. */
+ vf_info_local.physfn_pcidev = udev_device_new_from_syspath(udev, physfn_pci_syspath);
+ if (!vf_info_local.physfn_pcidev)
+ return -ENOENT;
+
+ /* Find the virtual function number by finding the right virtfn link. */
+ dir = opendir(physfn_pci_syspath);
+ if (!dir) {
+ r = -errno;
+ goto out_unref;
+ }
+ FOREACH_DIRENT_ALL(dent, dir, break) {
+ _cleanup_free_ char *virtfn_link_file = NULL;
+ if (!startswith(dent->d_name, "virtfn"))
+ continue;
+ virtfn_link_file = strjoin(physfn_pci_syspath, "/", dent->d_name);
+ if (!virtfn_link_file) {
+ r = -ENOMEM;
+ goto out_unref;
+ }
+ if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath) < 0)
+ continue;
+ if (streq(udev_device_get_syspath(names->pcidev), virtfn_pci_syspath)) {
+ if (!snprintf_ok(vf_info_local.suffix, sizeof(vf_info_local.suffix), "v%s", &dent->d_name[6])) {
+ r = -ENOENT;
+ goto out_unref;
+ }
+ break;
+ }
+ }
+ if (isempty(vf_info_local.suffix)) {
+ r = -ENOENT;
+ goto out_unref;
+ }
+ *vf_info = vf_info_local;
+ return 0;
+
+out_unref:
+ udev_device_unref(vf_info_local.physfn_pcidev);
+ return r;
+}
+
/* retrieve on-board index number and label from firmware */
static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
unsigned dev_port = 0;
@@ -231,20 +281,29 @@ static bool is_pci_multifunction(struct udev_device *dev) {
return false;
}
+static bool is_pci_ari_enabled(struct udev_device *dev) {
+ return streq_ptr(udev_device_get_sysattr_value(dev, "ari_enabled"), "1");
+}
+
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
struct udev *udev = udev_device_get_udev(names->pcidev);
- unsigned domain, bus, slot, func, dev_port = 0;
+ unsigned domain, bus, slot, func, dev_port = 0, hotplug_slot = 0;
size_t l;
char *s;
const char *attr, *port_name;
- _cleanup_udev_device_unref_ struct udev_device *pci = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *pci = NULL;
+ struct udev_device *hotplug_slot_dev;
char slots[PATH_MAX];
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *dent;
- int hotplug_slot = 0;
if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4)
return -ENOENT;
+ if (is_pci_ari_enabled(names->pcidev))
+ /* ARI devices support up to 256 functions on a single device ("slot"), and interpret the
+ * traditional 5-bit slot and 3-bit function number as a single 8-bit function number,
+ * where the slot makes up the upper 5 bits. */
+ func += slot * 8;
/* kernel provided port index for multiple ports on a single PCI function */
attr = udev_device_get_sysattr_value(dev, "dev_port");
@@ -281,27 +340,33 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
if (!dir)
return -errno;
- FOREACH_DIRENT_ALL(dent, dir, break) {
- int i;
- char *rest, str[PATH_MAX];
- _cleanup_free_ char *address = NULL;
-
- if (dent->d_name[0] == '.')
- continue;
- i = strtol(dent->d_name, &rest, 10);
- if (rest[0] != '\0')
- continue;
- if (i < 1)
- continue;
-
- if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, dent->d_name) &&
- read_one_line_file(str, &address) >= 0)
- /* match slot address with device by stripping the function */
- if (startswith(udev_device_get_sysname(names->pcidev), address))
- hotplug_slot = i;
-
+ hotplug_slot_dev = names->pcidev;
+ while (hotplug_slot_dev) {
+ FOREACH_DIRENT_ALL(dent, dir, break) {
+ unsigned i;
+ int r;
+ char str[PATH_MAX];
+ _cleanup_free_ char *address = NULL;
+
+ if (dent->d_name[0] == '.')
+ continue;
+ r = safe_atou_full(dent->d_name, 10, &i);
+ if (i < 1 || r < 0)
+ continue;
+
+ if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, dent->d_name) &&
+ read_one_line_file(str, &address) >= 0)
+ /* match slot address with device by stripping the function */
+ if (startswith(udev_device_get_sysname(hotplug_slot_dev), address))
+ hotplug_slot = i;
+
+ if (hotplug_slot > 0)
+ break;
+ }
if (hotplug_slot > 0)
break;
+ rewinddir(dir);
+ hotplug_slot_dev = udev_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL);
}
if (hotplug_slot > 0) {
@@ -406,6 +471,8 @@ static int names_platform(struct udev_device *dev, struct netnames *names, bool
static int names_pci(struct udev_device *dev, struct netnames *names) {
struct udev_device *parent;
+ struct netnames vf_names = {};
+ struct virtfn_info vf_info = {};
assert(dev);
assert(names);
@@ -426,8 +493,29 @@ static int names_pci(struct udev_device *dev, struct netnames *names) {
if (!names->pcidev)
return -ENOENT;
}
- dev_pci_onboard(dev, names);
- dev_pci_slot(dev, names);
+
+ if (get_virtfn_info(dev, names, &vf_info) >= 0) {
+ /* If this is an SR-IOV virtual device, get base name using physical device and add virtfn suffix. */
+ vf_names.pcidev = vf_info.physfn_pcidev;
+ dev_pci_onboard(dev, &vf_names);
+ dev_pci_slot(dev, &vf_names);
+ if (vf_names.pci_onboard[0])
+ if (strlen(vf_names.pci_onboard) + strlen(vf_info.suffix) < sizeof(names->pci_onboard))
+ strscpyl(names->pci_onboard, sizeof(names->pci_onboard),
+ vf_names.pci_onboard, vf_info.suffix, NULL);
+ if (vf_names.pci_slot[0])
+ if (strlen(vf_names.pci_slot) + strlen(vf_info.suffix) < sizeof(names->pci_slot))
+ strscpyl(names->pci_slot, sizeof(names->pci_slot),
+ vf_names.pci_slot, vf_info.suffix, NULL);
+ if (vf_names.pci_path[0])
+ if (strlen(vf_names.pci_path) + strlen(vf_info.suffix) < sizeof(names->pci_path))
+ strscpyl(names->pci_path, sizeof(names->pci_path),
+ vf_names.pci_path, vf_info.suffix, NULL);
+ udev_device_unref(vf_info.physfn_pcidev);
+ } else {
+ dev_pci_onboard(dev, names);
+ dev_pci_slot(dev, names);
+ }
return 0;
}
diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
index 40158e0afc..8bed6399af 100644
--- a/src/udev/udev-builtin-net_setup_link.c
+++ b/src/udev/udev-builtin-net_setup_link.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2013 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "link-config.h"
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 9ce2079a67..36f1949c7b 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -2,22 +2,9 @@
/*
* compose persistent device path
*
- * Copyright (C) 2009-2011 Kay Sievers <kay@vrfy.org>
*
* Logic based on Hannes Reinecke's shell script.
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
@@ -62,10 +49,8 @@ static void path_prepend(char **path, const char *fmt, ...) {
}
free_and_replace(*path, new);
- } else {
- *path = pre;
- pre = NULL;
- }
+ } else
+ *path = TAKE_PTR(pre);
}
/*
@@ -106,7 +91,7 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
struct udev *udev;
struct udev_device *targetdev;
- _cleanup_udev_device_unref_ struct udev_device *fcdev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *fcdev = NULL;
const char *port;
_cleanup_free_ char *lun = NULL;
@@ -135,7 +120,7 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent, char **path) {
struct udev *udev;
struct udev_device *targetdev, *target_parent;
- _cleanup_udev_device_unref_ struct udev_device *sasdev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *sasdev = NULL;
const char *sas_address;
_cleanup_free_ char *lun = NULL;
@@ -170,7 +155,7 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
{
struct udev *udev;
struct udev_device *targetdev, *target_parent, *port, *expander;
- _cleanup_udev_device_unref_ struct udev_device
+ _cleanup_(udev_device_unrefp) struct udev_device
*target_sasdev = NULL, *expander_sasdev = NULL, *port_sasdev = NULL;
const char *sas_address = NULL;
const char *phy_id;
@@ -246,7 +231,7 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) {
struct udev *udev;
struct udev_device *transportdev;
- _cleanup_udev_device_unref_ struct udev_device
+ _cleanup_(udev_device_unrefp) struct udev_device
*sessiondev = NULL, *conndev = NULL;
const char *target, *connname, *addr, *port;
_cleanup_free_ char *lun = NULL;
@@ -293,7 +278,7 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **path) {
struct udev *udev;
struct udev_device *targetdev, *target_parent;
- _cleanup_udev_device_unref_ struct udev_device *atadev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *atadev = NULL;
const char *port_no;
assert(parent);
@@ -397,16 +382,17 @@ static struct udev_device *handle_scsi_default(struct udev_device *parent, char
return hostdev;
}
-static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path) {
+static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path, size_t guid_str_len) {
struct udev_device *hostdev;
struct udev_device *vmbusdev;
const char *guid_str;
_cleanup_free_ char *lun = NULL;
- char guid[38];
+ char guid[39];
size_t i, k;
assert(parent);
assert(path);
+ assert(guid_str_len < sizeof(guid));
hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
if (!hostdev)
@@ -420,10 +406,10 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char *
if (!guid_str)
return NULL;
- if (strlen(guid_str) < 37 || guid_str[0] != '{' || guid_str[36] != '}')
+ if (strlen(guid_str) < guid_str_len || guid_str[0] != '{' || guid_str[guid_str_len-1] != '}')
return NULL;
- for (i = 1, k = 0; i < 36; i++) {
+ for (i = 1, k = 0; i < guid_str_len-1; i++) {
if (guid_str[i] == '-')
continue;
guid[k++] = guid_str[i];
@@ -472,7 +458,9 @@ static struct udev_device *handle_scsi(struct udev_device *parent, char **path,
return handle_scsi_ata(parent, path);
if (strstr(name, "/vmbus_"))
- return handle_scsi_hyperv(parent, path);
+ return handle_scsi_hyperv(parent, path, 37);
+ else if (strstr(name, "/VMBUS"))
+ return handle_scsi_hyperv(parent, path, 38);
return handle_scsi_default(parent, path);
}
diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c
index edea242e65..b1191ae7ff 100644
--- a/src/udev/udev-builtin-uaccess.c
+++ b/src/udev/udev-builtin-uaccess.c
@@ -2,21 +2,7 @@
/*
* manage device node user ACL
*
- * Copyright 2010-2012 Kay Sievers <kay@vrfy.org>
- * Copyright 2010 Lennart Poettering
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
index 6d22dfe82c..dcf21a2f44 100644
--- a/src/udev/udev-builtin-usb_id.c
+++ b/src/udev/udev-builtin-usb_id.c
@@ -5,20 +5,7 @@
* Copyright (c) 2005 SUSE Linux Products GmbH, Germany
* Author: Hannes Reinecke <hare@suse.de>
*
- * Copyright (C) 2005-2011 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
@@ -176,7 +163,7 @@ static int dev_if_packed_info(struct udev_device *dev, char *ifs_str, size_t len
return log_debug_errno(errno, "Error opening USB device 'descriptors' file: %m");
size = read(fd, buf, sizeof(buf));
- if (size < 18 || size == sizeof(buf))
+ if (size < 18 || (size_t) size >= sizeof(buf))
return -EIO;
ifs_str[0] = '\0';
diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
index db2b6874f8..576d83d378 100644
--- a/src/udev/udev-builtin.c
+++ b/src/udev/udev-builtin.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2007-2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <getopt.h>
#include <stdio.h>
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index 7b8110582d..efe7297f04 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -2,7 +2,6 @@
*
* libudev - interface to udev device information
*
- * Copyright (C) 2008 Kay Sievers <kay@vrfy.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index d0befba29c..fd8406d959 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2003-2013 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 6a3ee93ca2..333dcae6b9 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2003-2013 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -79,7 +66,7 @@ static int node_symlink(struct udev_device *dev, const char *node, const char *s
buf[len] = '\0';
if (streq(target, buf)) {
log_debug("preserve already existing symlink '%s' to '%s'", slink, target);
- label_fix(slink, true, false);
+ (void) label_fix(slink, LABEL_IGNORE_ENOENT);
utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW);
goto exit;
}
@@ -324,7 +311,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply,
/* set the defaults */
if (!selinux)
- mac_selinux_fix(devnode, true, false);
+ (void) mac_selinux_fix(devnode, LABEL_IGNORE_ENOENT);
if (!smack)
mac_smack_apply(devnode, SMACK_ATTR_ACCESS, NULL);
}
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 635811c59f..f029395884 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2003-2012 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
index 61179ce03d..7864f57aa5 100644
--- a/src/udev/udev-watch.c
+++ b/src/udev/udev-watch.c
@@ -1,21 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2009 Canonical Ltd.
- * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
+ * Copyright © 2009 Canonical Ltd.
+ * Copyright © 2009 Scott James Remnant <scott@netsplit.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
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
diff --git a/src/udev/udev.h b/src/udev/udev.h
index ea11c2d29e..4596d0ea01 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -2,21 +2,8 @@
#pragma once
/*
- * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2003-2010 Kay Sievers <kay@vrfy.org>
+ * Copyright © 2003 Greg Kroah-Hartman <greg@kroah.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
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/param.h>
diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c
index 9546a6ebaf..a84cc156cb 100644
--- a/src/udev/udevadm-control.c
+++ b/src/udev/udevadm-control.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2005-2011 Kay Sievers <kay@vrfy.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -44,7 +43,7 @@ static void print_help(void) {
}
static int adm_control(struct udev *udev, int argc, char *argv[]) {
- _cleanup_udev_ctrl_unref_ struct udev_ctrl *uctrl = NULL;
+ _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
int timeout = 60;
int rc = 1, c;
@@ -137,18 +136,17 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) {
break;
}
case 't': {
+ int r, seconds;
usec_t s;
- int seconds;
- int r;
r = parse_sec(optarg, &s);
if (r < 0)
return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg);
- if (((s + USEC_PER_SEC - 1) / USEC_PER_SEC) > INT_MAX)
+ if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX)
log_error("Timeout value is out of range.");
else {
- seconds = s != USEC_INFINITY ? (int) ((s + USEC_PER_SEC - 1) / USEC_PER_SEC) : INT_MAX;
+ seconds = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX;
timeout = seconds;
rc = 0;
}
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index dc3ae7484d..02408a4285 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <ctype.h>
#include <getopt.h>
@@ -114,7 +96,9 @@ static struct trie_node *node_lookup(const struct trie_node *node, uint8_t c) {
struct trie_child_entry search;
search.c = c;
- child = bsearch(&search, node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp);
+ child = bsearch_safe(&search,
+ node->children, node->children_count, sizeof(struct trie_child_entry),
+ trie_children_cmp);
if (child)
return child->child;
return NULL;
@@ -461,6 +445,7 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
FILE *f;
char line[LINE_MAX];
struct udev_list match_list;
+ int r = 0, err;
udev_list_init(udev, &match_list, false);
@@ -494,6 +479,7 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
if (line[0] == ' ') {
log_error("Error, MATCH expected but got '%s' in '%s':", line, filename);
+ r = -EINVAL;
break;
}
@@ -505,6 +491,7 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
case HW_MATCH:
if (len == 0) {
log_error("Error, DATA expected but got empty line in '%s':", filename);
+ r = -EINVAL;
state = HW_NONE;
udev_list_cleanup(&match_list);
break;
@@ -518,7 +505,9 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
/* first data */
state = HW_DATA;
- insert_data(trie, &match_list, line, filename);
+ err = insert_data(trie, &match_list, line, filename);
+ if (err < 0)
+ r = err;
break;
case HW_DATA:
@@ -531,19 +520,22 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
if (line[0] != ' ') {
log_error("Error, DATA expected but got '%s' in '%s':", line, filename);
+ r = -EINVAL;
state = HW_NONE;
udev_list_cleanup(&match_list);
break;
}
- insert_data(trie, &match_list, line, filename);
+ err = insert_data(trie, &match_list, line, filename);
+ if (err < 0)
+ r = err;
break;
};
}
fclose(f);
udev_list_cleanup(&match_list);
- return 0;
+ return r;
}
static void help(void) {
@@ -551,6 +543,7 @@ static void help(void) {
" -h --help Print this message\n"
" -V --version Print version of the program\n"
" -u --update Update the hardware database\n"
+ " -s --strict When updating, return non-zero exit value on any parsing error\n"
" --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n"
" -t --test=MODALIAS Query database and print result\n"
" -r --root=PATH Alternative root path in the filesystem\n\n"
@@ -568,6 +561,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
static const struct option options[] = {
{ "update", no_argument, NULL, 'u' },
{ "usr", no_argument, NULL, ARG_USR },
+ { "strict", no_argument, NULL, 's' },
{ "test", required_argument, NULL, 't' },
{ "root", required_argument, NULL, 'r' },
{ "version", no_argument, NULL, 'V' },
@@ -581,8 +575,9 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
struct trie *trie = NULL;
int err, c;
int rc = EXIT_SUCCESS;
+ bool strict = false;
- while ((c = getopt_long(argc, argv, "ut:r:Vh", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "ust:r:Vh", options, NULL)) >= 0)
switch(c) {
case 'u':
update = true;
@@ -590,6 +585,9 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
case ARG_USR:
hwdb_bin_dir = UDEVLIBEXECDIR;
break;
+ case 's':
+ strict = true;
+ break;
case 't':
test = optarg;
break;
@@ -646,7 +644,8 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
}
STRV_FOREACH(f, files) {
log_debug("reading file '%s'", *f);
- import_file(udev, trie, *f);
+ if (import_file(udev, trie, *f) < 0 && strict)
+ rc = EXIT_FAILURE;
}
strv_free(files);
@@ -680,7 +679,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
rc = EXIT_FAILURE;
}
- label_fix(hwdb_bin, false, false);
+ (void) label_fix(hwdb_bin, 0);
}
if (test) {
@@ -699,7 +698,8 @@ out:
if (trie) {
if (trie->root)
trie_node_cleanup(trie->root);
- strbuf_cleanup(trie->strings);
+ if (trie->strings)
+ strbuf_cleanup(trie->strings);
free(trie);
}
return rc;
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index 580e95095b..ff41290478 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2004-2009 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
@@ -173,7 +160,7 @@ static int stat_device(const char *name, bool export, const char *prefix) {
}
static int export_devices(struct udev *udev) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *udev_enumerate;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *udev_enumerate;
struct udev_list_entry *list_entry;
udev_enumerate = udev_enumerate_new(udev);
@@ -182,7 +169,7 @@ static int export_devices(struct udev *udev) {
udev_enumerate_scan_devices(udev_enumerate);
udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
- _cleanup_udev_device_unref_ struct udev_device *device;
+ _cleanup_(udev_device_unrefp) struct udev_device *device;
device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
if (device != NULL)
@@ -272,7 +259,7 @@ static void help(void) {
}
static int uinfo(struct udev *udev, int argc, char *argv[]) {
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
bool root = 0;
bool export = 0;
const char *export_prefix = NULL;
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index 028ef92bc2..b1e13553dc 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2004-2010 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -79,10 +66,10 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) {
bool prop = false;
bool print_kernel = false;
bool print_udev = false;
- _cleanup_udev_list_cleanup_ struct udev_list subsystem_match_list;
- _cleanup_udev_list_cleanup_ struct udev_list tag_match_list;
- _cleanup_udev_monitor_unref_ struct udev_monitor *udev_monitor = NULL;
- _cleanup_udev_monitor_unref_ struct udev_monitor *kernel_monitor = NULL;
+ _cleanup_(udev_list_cleanup) struct udev_list subsystem_match_list;
+ _cleanup_(udev_list_cleanup) struct udev_list tag_match_list;
+ _cleanup_(udev_monitor_unrefp) struct udev_monitor *udev_monitor = NULL;
+ _cleanup_(udev_monitor_unrefp) struct udev_monitor *kernel_monitor = NULL;
_cleanup_close_ int fd_ep = -1;
int fd_kernel = -1, fd_udev = -1;
struct epoll_event ep_kernel, ep_udev;
diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c
index 0af3e6412b..b8d428bcb4 100644
--- a/src/udev/udevadm-settle.c
+++ b/src/udev/udevadm-settle.c
@@ -1,21 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2006-2009 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2009 Canonical Ltd.
- * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
+ * Copyright © 2009 Canonical Ltd.
+ * Copyright © 2009 Scott James Remnant <scott@netsplit.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
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c
index f5a39a11c1..0d6cd46bd7 100644
--- a/src/udev/udevadm-test-builtin.c
+++ b/src/udev/udevadm-test-builtin.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2011 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index ef1f2f0269..e3d85597a8 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -1,20 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2004-2008 Kay Sievers <kay@vrfy.org>
+ * Copyright © 2003-2004 Greg Kroah-Hartman <greg@kroah.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
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -48,9 +35,9 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
const char *action = "add";
const char *syspath = NULL;
struct udev_list_entry *entry;
- _cleanup_udev_rules_unref_ struct udev_rules *rules = NULL;
- _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
- _cleanup_udev_event_unref_ struct udev_event *event = NULL;
+ _cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
+ _cleanup_(udev_event_unrefp) struct udev_event *event = NULL;
sigset_t mask, sigmask_orig;
int rc = 0, c;
diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c
index d979c1bc24..9c07a51869 100644
--- a/src/udev/udevadm-trigger.c
+++ b/src/udev/udevadm-trigger.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2008-2009 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -134,8 +121,8 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
TYPE_SUBSYSTEMS,
} device_type = TYPE_DEVICES;
const char *action = "change";
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *udev_enumerate = NULL;
- _cleanup_udev_monitor_unref_ struct udev_monitor *udev_monitor = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *udev_enumerate = NULL;
+ _cleanup_(udev_monitor_unrefp) struct udev_monitor *udev_monitor = NULL;
_cleanup_close_ int fd_ep = -1;
int fd_udev = -1;
struct epoll_event ep_udev;
@@ -230,7 +217,7 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
}
break;
case 'b': {
- _cleanup_udev_device_unref_ struct udev_device *dev;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev;
dev = find_device(udev, optarg, "/sys");
if (!dev) {
@@ -250,7 +237,7 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
break;
case ARG_NAME: {
- _cleanup_udev_device_unref_ struct udev_device *dev;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev;
dev = find_device(udev, optarg, "/dev/");
if (!dev) {
@@ -280,7 +267,7 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
}
for (; optind < argc; optind++) {
- _cleanup_udev_device_unref_ struct udev_device *dev;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev;
dev = find_device(udev, argv[optind], NULL);
if (!dev) {
@@ -355,7 +342,7 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
for (i = 0; i < fdcount; i++) {
if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) {
- _cleanup_udev_device_unref_ struct udev_device *device;
+ _cleanup_(udev_device_unrefp) struct udev_device *device;
const char *syspath = NULL;
device = udev_monitor_receive_device(udev_monitor);
diff --git a/src/udev/udevadm-util.c b/src/udev/udevadm-util.c
index b71b9ebd99..c570b72b8e 100644
--- a/src/udev/udevadm-util.c
+++ b/src/udev/udevadm-util.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2008-2009 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "path-util.h"
diff --git a/src/udev/udevadm-util.h b/src/udev/udevadm-util.h
index 8262a8343f..0b426e09f6 100644
--- a/src/udev/udevadm-util.h
+++ b/src/udev/udevadm-util.h
@@ -2,20 +2,6 @@
#pragma once
/*
- * Copyright (C) 2014 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "udev.h"
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index 06be1e8af5..0b79d2f91d 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -1,19 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2007-2012 Kay Sievers <kay@vrfy.org>
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index daaab6417a..34f6a95503 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -1,22 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca>
- * Copyright (C) 2009 Canonical Ltd.
- * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
+ * Copyright © 2004 Chris Friesen <chris_friesen@sympatico.ca>
+ * Copyright © 2009 Canonical Ltd.
+ * Copyright © 2009 Scott James Remnant <scott@netsplit.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
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -233,8 +220,7 @@ static int worker_new(struct worker **ret, Manager *manager, struct udev_monitor
if (r < 0)
return r;
- *ret = worker;
- worker = NULL;
+ *ret = TAKE_PTR(worker);
return 0;
}
@@ -325,9 +311,21 @@ static int worker_send_message(int fd) {
return loop_write(fd, &message, sizeof(message), false);
}
+static bool shall_lock_device(struct udev_device *dev) {
+ const char *sysname;
+
+ if (!streq_ptr("block", udev_device_get_subsystem(dev)))
+ return false;
+
+ sysname = udev_device_get_sysname(dev);
+ return !startswith(sysname, "dm-") &&
+ !startswith(sysname, "md") &&
+ !startswith(sysname, "drbd");
+}
+
static void worker_spawn(Manager *manager, struct event *event) {
struct udev *udev = event->udev;
- _cleanup_udev_monitor_unref_ struct udev_monitor *worker_monitor = NULL;
+ _cleanup_(udev_monitor_unrefp) struct udev_monitor *worker_monitor = NULL;
pid_t pid;
int r = 0;
@@ -353,8 +351,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
sigset_t mask;
/* take initial device from queue */
- dev = event->dev;
- event->dev = NULL;
+ dev = TAKE_PTR(event->dev);
unsetenv("NOTIFY_SOCKET");
@@ -427,9 +424,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
* udev has finished its event handling.
*/
if (!streq_ptr(udev_device_get_action(dev), "remove") &&
- streq_ptr("block", udev_device_get_subsystem(dev)) &&
- !startswith(udev_device_get_sysname(dev), "dm-") &&
- !startswith(udev_device_get_sysname(dev), "md")) {
+ shall_lock_device(dev)) {
struct udev_device *d = dev;
if (streq_ptr("partition", udev_device_get_devtype(d)))
@@ -923,8 +918,8 @@ static int on_uevent(sd_event_source *s, int fd, uint32_t revents, void *userdat
/* receive the udevd message from userspace */
static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Manager *manager = userdata;
- _cleanup_udev_ctrl_connection_unref_ struct udev_ctrl_connection *ctrl_conn = NULL;
- _cleanup_udev_ctrl_msg_unref_ struct udev_ctrl_msg *ctrl_msg = NULL;
+ _cleanup_(udev_ctrl_connection_unrefp) struct udev_ctrl_connection *ctrl_conn = NULL;
+ _cleanup_(udev_ctrl_msg_unrefp) struct udev_ctrl_msg *ctrl_msg = NULL;
const char *str;
int i;
@@ -1021,7 +1016,7 @@ static int synthesize_change(struct udev_device *dev) {
bool has_partitions = false;
int fd;
struct udev *udev = udev_device_get_udev(dev);
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item;
/*
@@ -1059,7 +1054,7 @@ static int synthesize_change(struct udev_device *dev) {
return r;
udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
if (!d)
@@ -1089,7 +1084,7 @@ static int synthesize_change(struct udev_device *dev) {
write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
if (!d)
@@ -1131,7 +1126,7 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
}
FOREACH_INOTIFY_EVENT(e, buffer, l) {
- _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
dev = udev_watch_lookup(manager->udev, e->wd);
if (!dev)
@@ -1258,7 +1253,7 @@ static int on_post(sd_event_source *s, void *userdata) {
}
static int listen_fds(int *rctrl, int *rnetlink) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
int ctrl_fd = -1, netlink_fd = -1;
int fd, n, r;
@@ -1288,7 +1283,7 @@ static int listen_fds(int *rctrl, int *rnetlink) {
}
if (ctrl_fd < 0) {
- _cleanup_udev_ctrl_unref_ struct udev_ctrl *ctrl = NULL;
+ _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *ctrl = NULL;
udev = udev_new();
if (!udev)
@@ -1312,7 +1307,7 @@ static int listen_fds(int *rctrl, int *rnetlink) {
}
if (netlink_fd < 0) {
- _cleanup_udev_monitor_unref_ struct udev_monitor *monitor = NULL;
+ _cleanup_(udev_monitor_unrefp) struct udev_monitor *monitor = NULL;
if (!udev) {
udev = udev_new();
@@ -1606,8 +1601,7 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
if (r < 0)
return log_error_errno(r, "error creating post event source: %m");
- *ret = manager;
- manager = NULL;
+ *ret = TAKE_PTR(manager);
return 0;
}
@@ -1743,8 +1737,6 @@ int main(int argc, char *argv[]) {
log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m");
}
-
-
pid = fork();
switch (pid) {
case 0:
diff --git a/src/udev/v4l_id/v4l_id.c b/src/udev/v4l_id/v4l_id.c
index 8c525c1139..4d482891a1 100644
--- a/src/udev/v4l_id/v4l_id.c
+++ b/src/udev/v4l_id/v4l_id.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2009 Kay Sievers <kay@vrfy.org>
* Copyright (c) 2009 Filippo Argiolas <filippo.argiolas@gmail.com>
*
* This program is free software; you can redistribute it and/or
diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c
index ccf2d47196..22faf19fa3 100644
--- a/src/update-done/update-done.c
+++ b/src/update-done/update-done.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "alloc-util.h"
#include "fileio-label.h"
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index e16f67be29..70ed723a8e 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
diff --git a/src/user-sessions/user-sessions.c b/src/user-sessions/user-sessions.c
index 8e8d43e1d4..89c4b0005d 100644
--- a/src/user-sessions/user-sessions.c
+++ b/src/user-sessions/user-sessions.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <unistd.h>
diff --git a/src/vconsole/meson.build b/src/vconsole/meson.build
index 745aec4f14..03065ec26c 100644
--- a/src/vconsole/meson.build
+++ b/src/vconsole/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
if conf.get('ENABLE_VCONSOLE') == 1
vconsole_rules = configure_file(
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index a9cc2bf63c..f162d29220 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -1,22 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Kay Sievers
- Copyright 2016 Michal Soltys <soltys@ziu.info>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Michal Soltys <soltys@ziu.info>
***/
#include <errno.h>
@@ -49,35 +33,42 @@
#include "virt.h"
static int verify_vc_device(int fd) {
- unsigned char data[1];
+ unsigned char data[] = {
+ TIOCL_GETFGCONSOLE,
+ };
+
int r;
- data[0] = TIOCL_GETFGCONSOLE;
r = ioctl(fd, TIOCLINUX, data);
- return r < 0 ? -errno : r;
+ if (r < 0)
+ return -errno;
+
+ return r;
}
static int verify_vc_allocation(unsigned idx) {
char vcname[sizeof("/dev/vcs") + DECIMAL_STR_MAX(unsigned) - 2];
- int r;
xsprintf(vcname, "/dev/vcs%u", idx);
- r = access(vcname, F_OK);
- return r < 0 ? -errno : r;
+
+ if (access(vcname, F_OK) < 0)
+ return -errno;
+
+ return 0;
}
static int verify_vc_allocation_byfd(int fd) {
struct vt_stat vcs = {};
- int r;
- r = ioctl(fd, VT_GETSTATE, &vcs);
- return r < 0 ? -errno : verify_vc_allocation(vcs.v_active);
+ if (ioctl(fd, VT_GETSTATE, &vcs) < 0)
+ return -errno;
+
+ return verify_vc_allocation(vcs.v_active);
}
static int verify_vc_kbmode(int fd) {
- int r, curr_mode;
+ int curr_mode;
- r = ioctl(fd, KDGKBMODE, &curr_mode);
/*
* Make sure we only adjust consoles in K_XLATE or K_UNICODE mode.
* Otherwise we would (likely) interfere with X11's processing of the
@@ -85,7 +76,8 @@ static int verify_vc_kbmode(int fd) {
*
* http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
*/
- if (r < 0)
+
+ if (ioctl(fd, KDGKBMODE, &curr_mode) < 0)
return -errno;
return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY;
@@ -129,7 +121,6 @@ static int toggle_utf8_sysfs(bool utf8) {
}
static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) {
- _cleanup_free_ char *cmd = NULL;
const char *args[8];
unsigned i = 0;
pid_t pid;
@@ -150,8 +141,12 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m
args[i++] = map_toggle;
args[i++] = NULL;
- log_debug("Executing \"%s\"...",
- strnull((cmd = strv_join((char**) args, " "))));
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *cmd;
+
+ cmd = strv_join((char**) args, " ");
+ log_debug("Executing \"%s\"...", strnull(cmd));
+ }
r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
@@ -165,7 +160,6 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m
}
static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) {
- _cleanup_free_ char *cmd = NULL;
const char *args[9];
unsigned i = 0;
pid_t pid;
@@ -190,8 +184,12 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
args[i++] = font;
args[i++] = NULL;
- log_debug("Executing \"%s\"...",
- strnull((cmd = strv_join((char**) args, " "))));
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *cmd;
+
+ cmd = strv_join((char**) args, " ");
+ log_debug("Executing \"%s\"...", strnull(cmd));
+ }
r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
@@ -325,8 +323,8 @@ static void setup_remaining_vcs(int src_fd, unsigned src_idx, bool utf8) {
static int find_source_vc(char **ret_path, unsigned *ret_idx) {
_cleanup_free_ char *path = NULL;
+ int r, err = 0;
unsigned i;
- int ret_fd, r, err = 0;
path = new(char, sizeof("/dev/tty63"));
if (!path)
@@ -358,20 +356,17 @@ static int find_source_vc(char **ret_path, unsigned *ret_idx) {
/* all checks passed, return this one as a source console */
*ret_idx = i;
- *ret_path = path;
- path = NULL;
- ret_fd = fd;
- fd = -1;
- return ret_fd;
+ *ret_path = TAKE_PTR(path);
+ return TAKE_FD(fd);
}
return log_error_errno(err, "No usable source console found: %m");
}
static int verify_source_vc(char **ret_path, const char *src_vc) {
- char *path;
_cleanup_close_ int fd = -1;
- int ret_fd, r;
+ char *path;
+ int r;
fd = open_terminal(src_vc, O_RDWR|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
@@ -394,9 +389,7 @@ static int verify_source_vc(char **ret_path, const char *src_vc) {
return log_oom();
*ret_path = path;
- ret_fd = fd;
- fd = -1;
- return ret_fd;
+ return TAKE_FD(fd);
}
int main(int argc, char **argv) {
@@ -419,13 +412,12 @@ int main(int argc, char **argv) {
fd = verify_source_vc(&vc, argv[1]);
else
fd = find_source_vc(&vc, &idx);
-
if (fd < 0)
return EXIT_FAILURE;
utf8 = is_locale_utf8();
- r = parse_env_file("/etc/vconsole.conf", NEWLINE,
+ r = parse_env_file(NULL, "/etc/vconsole.conf", NEWLINE,
"KEYMAP", &vc_keymap,
"KEYMAP_TOGGLE", &vc_keymap_toggle,
"FONT", &vc_font,
@@ -437,7 +429,7 @@ int main(int argc, char **argv) {
/* Let the kernel command line override /etc/vconsole.conf */
if (detect_container() <= 0) {
- r = parse_env_file("/proc/cmdline", WHITESPACE,
+ r = parse_env_file(NULL, "/proc/cmdline", WHITESPACE,
"vconsole.keymap", &vc_keymap,
"vconsole.keymap_toggle", &vc_keymap_toggle,
"vconsole.font", &vc_font,
diff --git a/src/veritysetup/veritysetup-generator.c b/src/veritysetup/veritysetup-generator.c
index d09f295392..0c63c5eaad 100644
--- a/src/veritysetup/veritysetup-generator.c
+++ b/src/veritysetup/veritysetup-generator.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdbool.h>
diff --git a/src/veritysetup/veritysetup.c b/src/veritysetup/veritysetup.c
index 3b4e72bf9e..795af77aa6 100644
--- a/src/veritysetup/veritysetup.c
+++ b/src/veritysetup/veritysetup.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <stdio.h>
diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c
index 56aaa373ff..bc786c9734 100644
--- a/src/volatile-root/volatile-root.c
+++ b/src/volatile-root/volatile-root.c
@@ -1,22 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <sys/mount.h>
diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf
index e263cf0628..b67ae87ca6 100644
--- a/sysctl.d/50-default.conf
+++ b/sysctl.d/50-default.conf
@@ -33,6 +33,9 @@ net.ipv4.conf.all.promote_secondaries = 1
# Fair Queue CoDel packet scheduler to fight bufferbloat
net.core.default_qdisc = fq_codel
+# Request Explicit Congestion Notification (ECN) on both in and outgoing connections
+net.ipv4.tcp_ecn = 1
+
# Enable hard and soft link protection
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
diff --git a/sysctl.d/meson.build b/sysctl.d/meson.build
index 1e612de41e..64f6ce942e 100644
--- a/sysctl.d/meson.build
+++ b/sysctl.d/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
install_data(
'50-default.conf',
diff --git a/sysusers.d/meson.build b/sysusers.d/meson.build
index a240761837..eb99957e2f 100644
--- a/sysusers.d/meson.build
+++ b/sysusers.d/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
in_files = ['basic.conf']
@@ -41,7 +26,7 @@ foreach file : m4_files
'sysusers.d_' + file,
input : file + '.m4',
output: file,
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : enable_sysusers,
install_dir : sysusersdir)
diff --git a/sysusers.d/systemd.conf.m4 b/sysusers.d/systemd.conf.m4
index 82e23ca5a8..2315b56e3f 100644
--- a/sysusers.d/systemd.conf.m4
+++ b/sysusers.d/systemd.conf.m4
@@ -6,12 +6,6 @@
# (at your option) any later version.
g systemd-journal - -
-m4_ifdef(`ENABLE_NETWORKD',
-u systemd-network - "systemd Network Management"
-)m4_dnl
-m4_ifdef(`ENABLE_RESOLVE',
-u systemd-resolve - "systemd Resolver"
-)m4_dnl
m4_ifdef(`ENABLE_COREDUMP',
u systemd-coredump - "systemd Core Dumper"
)m4_dnl
diff --git a/test/TEST-03-JOBS/test-jobs.sh b/test/TEST-03-JOBS/test-jobs.sh
index 4c954d0397..e66ea53621 100755
--- a/test/TEST-03-JOBS/test-jobs.sh
+++ b/test/TEST-03-JOBS/test-jobs.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -e
+#!/bin/bash -ex
# Test merging of a --job-mode=ignore-dependencies job into a previously
# installed job.
diff --git a/test/TEST-03-JOBS/test.sh b/test/TEST-03-JOBS/test.sh
index 88bbf3cdac..08e5cfe6c8 100755
--- a/test/TEST-03-JOBS/test.sh
+++ b/test/TEST-03-JOBS/test.sh
@@ -3,6 +3,7 @@
# ex: ts=8 sw=4 sts=4 et filetype=sh
set -e
TEST_DESCRIPTION="Job-related tests"
+TEST_NO_QEMU=1
. $TEST_BASE_DIR/test-functions
@@ -27,6 +28,8 @@ After=multi-user.target
[Service]
ExecStart=/test-jobs.sh
Type=oneshot
+StandardOutput=tty
+StandardError=tty
EOF
# copy the units used by this test
diff --git a/test/TEST-06-SELINUX/test.sh b/test/TEST-06-SELINUX/test.sh
index e0c4c10e1c..604ede5b2b 100755
--- a/test/TEST-06-SELINUX/test.sh
+++ b/test/TEST-06-SELINUX/test.sh
@@ -10,6 +10,9 @@ TEST_NO_NSPAWN=1
# selinux-policy-targeted
# selinux-policy-devel
+# Check if selinux-policy-devel is installed, and if it isn't bail out early instead of failing
+test -f /usr/share/selinux/devel/include/system/systemd.if || exit 0
+
. $TEST_BASE_DIR/test-functions
SETUP_SELINUX=yes
KERNEL_APPEND="$KERNEL_APPEND selinux=1 security=selinux"
diff --git a/test/TEST-15-DROPIN/test.sh b/test/TEST-15-DROPIN/test.sh
index b85bffafaf..cc0d56da8a 100755
--- a/test/TEST-15-DROPIN/test.sh
+++ b/test/TEST-15-DROPIN/test.sh
@@ -9,7 +9,7 @@ TEST_NO_QEMU=1
test_setup() {
# create the basic filesystem layout
- setup_basic_environment >/dev/null
+ setup_basic_environment
# mask some services that we do not want to run in these tests
ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
diff --git a/test/TEST-16-EXTEND-TIMEOUT/test.sh b/test/TEST-16-EXTEND-TIMEOUT/test.sh
index 4544672066..e7bb5430c0 100755
--- a/test/TEST-16-EXTEND-TIMEOUT/test.sh
+++ b/test/TEST-16-EXTEND-TIMEOUT/test.sh
@@ -4,6 +4,7 @@
set -e
TEST_DESCRIPTION="EXTEND_TIMEOUT_USEC=usec start/runtime/stop tests"
SKIP_INITRD=yes
+TEST_NO_QEMU=1
. $TEST_BASE_DIR/test-functions
diff --git a/test/TEST-21-SYSUSERS/test-11.expected-group b/test/TEST-21-SYSUSERS/test-11.expected-group
new file mode 100644
index 0000000000..815a6c5940
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-11.expected-group
@@ -0,0 +1,6 @@
+o1:x:100:
+g1:x:111:
+u1:x:222:
++giant:::bill,tina,alan,hetty
+-transport:::
++:::
diff --git a/test/TEST-21-SYSUSERS/test-11.expected-passwd b/test/TEST-21-SYSUSERS/test-11.expected-passwd
new file mode 100644
index 0000000000..3f9ab3901f
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-11.expected-passwd
@@ -0,0 +1,6 @@
+root:x:0:0:root:/root:/bin/bash
+systemd-network:x:492:492:Systemd Network Management:/:/usr/sbin/nologin
+systemd-resolve:x:491:491:Systemd Resolver:/:/usr/sbin/nologin
+systemd-timesync:x:493:493:Systemd Time Synchronization:/:/usr/sbin/nologin
+u1:x:222:222::/:/sbin/nologin
++::::::
diff --git a/test/TEST-21-SYSUSERS/test-11.initial-group b/test/TEST-21-SYSUSERS/test-11.initial-group
new file mode 100644
index 0000000000..88d31f2c72
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-11.initial-group
@@ -0,0 +1,4 @@
+o1:x:100
++giant:::bill,tina,alan,hetty
+-transport:::
++:::
diff --git a/test/TEST-21-SYSUSERS/test-11.initial-passwd b/test/TEST-21-SYSUSERS/test-11.initial-passwd
new file mode 100644
index 0000000000..45d3ffd5c2
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-11.initial-passwd
@@ -0,0 +1,5 @@
+root:x:0:0:root:/root:/bin/bash
+systemd-network:x:492:492:Systemd Network Management:/:/usr/sbin/nologin
+systemd-resolve:x:491:491:Systemd Resolver:/:/usr/sbin/nologin
+systemd-timesync:x:493:493:Systemd Time Synchronization:/:/usr/sbin/nologin
++::::::
diff --git a/test/TEST-21-SYSUSERS/test-11.input b/test/TEST-21-SYSUSERS/test-11.input
new file mode 100644
index 0000000000..bffc2cd7ea
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-11.input
@@ -0,0 +1,3 @@
+#Type Name ID GECOS HOMEDIR
+u u1 222 - -
+g g1 111 - -
diff --git a/test/TEST-21-SYSUSERS/test-12.expected-group b/test/TEST-21-SYSUSERS/test-12.expected-group
new file mode 100644
index 0000000000..5d94846ed1
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-12.expected-group
@@ -0,0 +1,2 @@
+root:x:0:
+systemd-coredump:x:1:
diff --git a/test/TEST-21-SYSUSERS/test-12.expected-passwd b/test/TEST-21-SYSUSERS/test-12.expected-passwd
new file mode 100644
index 0000000000..75fe9b420d
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-12.expected-passwd
@@ -0,0 +1,2 @@
+root:x:0:0:root:/root:/bin/bash
+systemd-coredump:x:1:1:systemd Core Dumper:/:/sbin/nologin
diff --git a/test/TEST-21-SYSUSERS/test-12.initial-group b/test/TEST-21-SYSUSERS/test-12.initial-group
new file mode 100644
index 0000000000..1dbf9013ee
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-12.initial-group
@@ -0,0 +1 @@
+root:x:0:
diff --git a/test/TEST-21-SYSUSERS/test-12.initial-passwd b/test/TEST-21-SYSUSERS/test-12.initial-passwd
new file mode 100644
index 0000000000..aebc4923f4
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-12.initial-passwd
@@ -0,0 +1 @@
+root:x:0:0:root:/root:/bin/bash
diff --git a/test/TEST-21-SYSUSERS/test-12.input b/test/TEST-21-SYSUSERS/test-12.input
new file mode 100644
index 0000000000..2913120276
--- /dev/null
+++ b/test/TEST-21-SYSUSERS/test-12.input
@@ -0,0 +1 @@
+u systemd-coredump 1 "systemd Core Dumper"
diff --git a/test/TEST-21-SYSUSERS/test.sh b/test/TEST-21-SYSUSERS/test.sh
index bebbab9d23..73cbe10b69 100755
--- a/test/TEST-21-SYSUSERS/test.sh
+++ b/test/TEST-21-SYSUSERS/test.sh
@@ -10,6 +10,13 @@ test_setup() {
mkdir -p $TESTDIR/etc/sysusers.d $TESTDIR/usr/lib/sysusers.d $TESTDIR/tmp
}
+prepare_testdir() {
+ rm -f $TESTDIR/etc/*{passwd,group,shadow}
+ for i in $1.initial-{passwd,group,shadow}; do
+ test -f $i && cp $i $TESTDIR/etc/${i#*.initial-}
+ done
+}
+
preprocess() {
in="$1"
@@ -41,7 +48,7 @@ test_run() {
# happy tests
for f in test-*.input; do
echo "*** Running $f"
- rm -f $TESTDIR/etc/*{passwd,group,shadow}
+ prepare_testdir ${f%.input}
cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
systemd-sysusers --root=$TESTDIR
@@ -50,7 +57,7 @@ test_run() {
for f in test-*.input; do
echo "*** Running $f on stdin"
- rm -f $TESTDIR/etc/*{passwd,group,shadow}
+ prepare_testdir ${f%.input}
touch $TESTDIR/etc/sysusers.d/test.conf
cat $f | systemd-sysusers --root=$TESTDIR -
@@ -59,7 +66,7 @@ test_run() {
for f in test-*.input; do
echo "*** Running $f on stdin with --replace"
- rm -f $TESTDIR/etc/*{passwd,group,shadow}
+ prepare_testdir ${f%.input}
touch $TESTDIR/etc/sysusers.d/test.conf
# this overrides test.conf which is masked on disk
cat $f | systemd-sysusers --root=$TESTDIR --replace=/etc/sysusers.d/test.conf -
@@ -71,7 +78,7 @@ test_run() {
# test --inline
echo "*** Testing --inline"
- rm -f $TESTDIR/etc/*{passwd,group,shadow}
+ prepare_testdir
# copy a random file to make sure it is ignored
cp $f $TESTDIR/etc/sysusers.d/confuse.conf
systemd-sysusers --root=$TESTDIR --inline \
@@ -82,7 +89,7 @@ test_run() {
# test --replace
echo "*** Testing --inline with --replace"
- rm -f $TESTDIR/etc/*{passwd,group,shadow}
+ prepare_testdir
# copy a random file to make sure it is ignored
cp $f $TESTDIR/etc/sysusers.d/confuse.conf
systemd-sysusers --root=$TESTDIR \
@@ -98,7 +105,7 @@ test_run() {
# tests for error conditions
for f in unhappy-*.input; do
echo "*** Running test $f"
- rm -f $TESTDIR/etc/*{passwd,group,shadow}
+ prepare_testdir ${f%.input}
cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
systemd-sysusers --root=$TESTDIR 2> /dev/null
journalctl -t systemd-sysusers -o cat | tail -n1 > $TESTDIR/tmp/err
diff --git a/test/TEST-22-TMPFILES/test.sh b/test/TEST-22-TMPFILES/test.sh
index ca78933380..5b8abbfff5 100755
--- a/test/TEST-22-TMPFILES/test.sh
+++ b/test/TEST-22-TMPFILES/test.sh
@@ -9,7 +9,7 @@ TEST_NO_QEMU=1
test_setup() {
# create the basic filesystem layout
- setup_basic_environment >/dev/null
+ setup_basic_environment
inst_binary mv
inst_binary stat
inst_binary seq
diff --git a/test/create-sys-script.py b/test/create-sys-script.py
index e25f3b4f8f..d03ca2cbf9 100755
--- a/test/create-sys-script.py
+++ b/test/create-sys-script.py
@@ -6,22 +6,8 @@ OUTFILE_HEADER = """#!/usr/bin/env python3
#
# create-sys-script.py
#
-# (C) 2017 Canonical Ltd.
+# © 2017 Canonical Ltd.
# Author: Dan Streetman <dan.streetman@canonical.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/>.
-#
"""
# Use this only to (re-)create the test/sys-script.py script,
diff --git a/test/fuzz-corpus/.gitattributes b/test/fuzz-corpus/.gitattributes
new file mode 100644
index 0000000000..7b1b3e1835
--- /dev/null
+++ b/test/fuzz-corpus/.gitattributes
@@ -0,0 +1 @@
+/*/* -whitespace
diff --git a/test/fuzz-corpus/journal-remote/invalid-ts.txt b/test/fuzz-corpus/journal-remote/invalid-ts.txt
new file mode 100644
index 0000000000..bc036fdcb0
--- /dev/null
+++ b/test/fuzz-corpus/journal-remote/invalid-ts.txt
Binary files differ
diff --git a/test/fuzz-corpus/journal-remote/sample.txt b/test/fuzz-corpus/journal-remote/sample.txt
new file mode 100644
index 0000000000..891c0003ef
--- /dev/null
+++ b/test/fuzz-corpus/journal-remote/sample.txt
@@ -0,0 +1,180 @@
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d7;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501873
+__MONOTONIC_TIMESTAMP=1753961140951
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=\x1b\r"\x9a\xea]\x90rU\xb0SX5\nY\xebi\xdac\x1f\xde\xb4\xf6\x0e\x8d/!\xd0\x9a\xe8\x8b\xc3#hN\xf4\x9c\x8e\xc5\x92>\xaa\xf8Ih\x13\xd2\xbbOa\xedK\x04\xa449\xf3f\x9e\xfc=\xc9\xc1\x0fe\xb4\xf96\xd5z\xcfQ\xcb\xb1\xb4\xe48\xb3\x9f\x1b
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483516
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000000
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d8;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501874
+__MONOTONIC_TIMESTAMP=1753961140952
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=l\x1a\xf4^\xb1\x14\xfb@\r\xa1\x11\xda0\xe0]3Ms$\x7f06\xde\xd9\x02y\xf9@\n\xe8\x01\x83\xcb\xe0)\xed\x98*>\xa1\xc2Y\xe8IR\x95h\xa1\xbb\x16\xba\xedK\x11\xfcj\x04\xfb\x0b\x9b)p\x10\xecH\x1f\x0b\x89{\xeb'\x0e\x1d\xaa\xcbZ\x86\xe0k1
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483517
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000001
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d9;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501875
+__MONOTONIC_TIMESTAMP=1753961140953
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=MzV_\xbb\xc1\x14f\x84\x15\xf5\xe0\xe6\xd2\x0e6#N\xf1\x1b\xe9Z*\x8f\x8a\x13\xad\xa4%r\x02\xd1\xc4^U\xc0u!\xdfjl\x15\xb6\xcc\x93\x1dRi<\x1a\xa9/\x9c\xcb\xe8\x99\xe3\x1cN\x06\xf0\xb41a\xa7L\x99\xda\x83Q: ]\x1c\xb9Hiz\n\x94
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483518
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000002
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12da;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501876
+__MONOTONIC_TIMESTAMP=1753961140954
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=\x8aF\xfcG\xd7\xeeZ\x86\xcb.O\xb1!,2\xbf\x86\\&\x15\xa7\xe6\xe7-\x81\xed\xf8\x7f=\xf7\x90YF\xe1\xe6\x99\x83\x84\r\xe48\x93\xc7\xdd\tJy\x86\\\xb4\xf9\xefT\r\x04\xae\x1d\x99\xfe'\x99m\xc4#\x8d\x89w\xb1\xecC\xaf\xe6\x1b\xfd\xc5\xbc\xfd\xe3w2
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483519
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000003
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12db;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501877
+__MONOTONIC_TIMESTAMP=1753961140955
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=`\xc7\r\xb6\xc3NPjc\xa129L\xe1\x17\xa2\x96\xa8w\x0c\x07\x8f\x98\x1eS-N\xb7lt\xc5=\xd1\x93\x10_1\xdc\xa9x\xd1\x8a\n\xb1\x90\xdca\xc4\x94\x98\x92\x00\x90)d{\x96\x9e\xc2A\xbf\x81s\xf82_\xe0;\xc3\x06\x8eO\xe4\x8a5GX\xe1\xff\xea
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483520
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000004
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12dc;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501878
+__MONOTONIC_TIMESTAMP=1753961140956
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=\r\t \xdf-\xed\xd5\xde\xa1/\xa5T\x1a\xdd\xf9a\xe2\x8b()\xd5\xf2\x1b\xbcu~\xaa\x97\xc7~\x0e~2\x11\xa0\xb5\xd3\xd7^ \xea\x16\x02{\xd1\xbe\xa02\xad\x00\xba$\xf2\xd5\x7f\x9a\xf0\xf9\xf2\x14\xf0/\xb5\xd3"`\xd8\x8e\xb6w\x1bP\x96\xf1\x0c\xf0#\xd2\x12\x88
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483521
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000005
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12dd;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501879
+__MONOTONIC_TIMESTAMP=1753961140957
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=\x1a\x15\xd3\x8d\x98\x83m\xe2\x02\xfa\x81\x98\xef\xa2\x8a\xcc\x10\xc5=q=\xd0\xd7_\x0e\x92D\xb1\xc7 \xaa\xae-\x18\xff\xb0<l5\xf1\x91-\xe8g! \xd8\xac\xadi"\xf8 \xebL\xe6-\xbf=i_@\x9b)B\xac\xa50\xf9\xf1~\xb1c^pTD\x15\xee}
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483522
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000006
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12de;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501880
+__MONOTONIC_TIMESTAMP=1753961140958
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=\xe4L \xb4\t\xf3\xfbQ\xb8\x95f{C\x1b\x91\x81\xd2!\xc0f\xa41=\xff\x84W\xf3\x0f=\x9e\x87\xd1\x9f\x86;F\x12\xd6\x1c6B\x07\x08\xdb*\xeem\x9f\xe7\xda\x81n_\x00^\xcf!\x19\x19\xe0\x9cM\x05\xf0\xe9\xe9=\xbc\xba=`inw\xc4Qq\x9cW\xe6
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483523
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000007
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12df;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501881
+__MONOTONIC_TIMESTAMP=1753961140959
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=\xda\x80\xe0\xe5@\xa4\x94\xecL\xbd\xe4\xe5\xbd\xc8\xae\x8e\xa9k\xa4\rt\xf2\x17\xe3n!.\xe3\xab*\xe3f{H\x98\x86\xa1=U-\x8cNd+\x90\xbd\x970d\xf7\xee\xd7g\x08c\x12\xf4\x9f3\xd0&\x95\xb0\xac\x1a\xe9k\xda,}\x97`:u\xad\x9e\xfaLj\x11
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483524
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000008
+
+__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12e0;t=4fd05c
+__REALTIME_TIMESTAMP=1404101101501882
+__MONOTONIC_TIMESTAMP=1753961140960
+_BOOT_ID=f446871715504074bf7049ef0718fa93
+_TRANSPORT=syslog
+PRIORITY=3
+SYSLOG_FACILITY=6
+SYSLOG_IDENTIFIER=/USR/SBIN/CRON
+MESSAGE=\xc0\xb4\xefIe\xc9\xd0\xaf!y\x13\xfdT(k\x9b\xc7\x7fm;\xc2\xbb"\x81\x87\\(-\x9a\x8b\xdd\x17\xf7\x8a\x92\xbd\xdd;\x9f\x99\x87\xf2\xb7\xcf\xf6XtRC\xad\xebT\xa1\xe5\xd9p\xd70\xc1\xb0^\x88g@=\xeb\xd8\xcf\xb7bK"6 \xda\x08\x1bp\xbc\r
+_UID=0
+_GID=0
+_MACHINE_ID=69121ca41d12c1b69a7960174c27b618
+_HOSTNAME=hostname
+SYSLOG_PID=25721
+_PID=25721
+_SOURCE_REALTIME_TIMESTAMP=1404101101483525
+DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000009
+
diff --git a/test/fuzz-corpus/unit-file/dev-mapper-fedora_krowka\x2dswap.swap b/test/fuzz-corpus/unit-file/dev-mapper-fedora_krowka\x2dswap.swap
new file mode 100644
index 0000000000..2886021b1a
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/dev-mapper-fedora_krowka\x2dswap.swap
@@ -0,0 +1,10 @@
+swap
+[Unit]
+SourcePath=/etc/fstab
+Documentation=man:fstab(5) man:systemd-fstab-generator(8)
+
+[Swap]
+What=/dev/mapper/fedora_krowka-swap
+Options=defaults,x-systemd.device-timeout=0
+Priority=11
+TimeoutSec=123h 5min 2y
diff --git a/test/fuzz-corpus/unit-file/directives.service b/test/fuzz-corpus/unit-file/directives.service
new file mode 100644
index 0000000000..c2334d3b19
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/directives.service
@@ -0,0 +1,910 @@
+service
+Accept=
+AccuracySec=
+After=
+Alias=
+AllowIsolate=
+Also=
+AmbientCapabilities=
+AssertACPower=
+AssertArchitecture=
+AssertCapability=
+AssertControlGroupController=
+AssertDirectoryNotEmpty=
+AssertFileIsExecutable=
+AssertFileNotEmpty=
+AssertFirstBoot=
+AssertGroup=
+AssertHost=
+AssertKernelCommandLine=
+AssertKernelVersion=
+AssertNeedsUpdate=
+AssertPathExists=
+AssertPathExistsGlob=
+AssertPathIsDirectory=
+AssertPathIsMountPoint=
+AssertPathIsReadWrite=
+AssertPathIsSymbolicLink=
+AssertSecurity=
+AssertUser=
+AssertVirtualization=
+Backlog=
+Before=
+BindIPv6Only=
+BindPaths=
+BindReadOnlyPaths=
+BindToDevice=
+BindsTo=
+BlockIOAccounting=
+BlockIODeviceWeight=
+BlockIOReadBandwidth=
+BlockIOWeight=
+BlockIOWriteBandwidth=
+Broadcast=
+BusName=
+CPUAccounting=
+CPUQuota=
+CPUShares=
+CPUWeight=
+CapabilityBoundingSet=
+CollectMode=
+ConditionACPower=
+ConditionArchitecture=
+ConditionCapability=
+ConditionControlGroupController=
+ConditionDirectoryNotEmpty=
+ConditionFileIsExecutable=
+ConditionFileNotEmpty=
+ConditionFirstBoot=
+ConditionGroup=
+ConditionHost=
+ConditionKernelCommandLine=
+ConditionKernelVersion=
+ConditionNeedsUpdate=
+ConditionPathExists=
+ConditionPathExistsGlob=
+ConditionPathIsDirectory=
+ConditionPathIsMountPoint=
+ConditionPathIsReadWrite=
+ConditionPathIsSymbolicLink=
+ConditionSecurity=
+ConditionUser=
+ConditionVirtualization=
+Conflicts=
+DefaultDependencies=
+DefaultInstance=
+DeferAcceptSec=
+Delegate=
+Description=
+DeviceAllow=
+DevicePolicy=
+DirectoryMode=
+DirectoryNotEmpty=
+Documentation=
+DynamicUser=
+ExecReload=
+ExecStart=
+ExecStartPost=
+ExecStartPre=
+ExecStop=
+ExecStopPost=
+ExecStopPre=
+FailureAction=
+FileDescriptorName=
+FileDescriptorStoreMax=
+ForceUnmount=
+FreeBind=
+Group=
+GuessMainPID=
+IOAccounting=
+IODeviceWeight=
+IOReadBandwidthMax=
+IOReadIOPSMax=
+IOWeight=
+IOWriteBandwidthMax=
+IOWriteIOPSMax=
+IPAccounting=
+IPAddressAllow=
+IPAddressDeny=
+IPTOS=
+IPTTL=
+IgnoreOnIsolate=
+JobRunningTimeoutSec=
+JobTimeoutAction=
+JobTimeoutRebootArgument=
+JobTimeoutSec=
+JoinsNamespaceOf=
+KeepAlive=
+KeepAliveIntervalSec=
+KeepAliveProbes=
+KeepAliveTimeSec=
+KillMode=
+KillSignal=
+LazyUnmount=
+ListenDatagram=
+ListenFIFO=
+ListenMessageQueue=
+#ListenNetlink=
+ListenSequentialPacket=
+ListenSpecial=
+ListenStream=
+ListenUSBFunction=
+MakeDirectory=
+Mark=
+MaxConnections=
+MaxConnectionsPerSource=
+MemoryAccounting=
+MemoryHigh=
+MemoryLimit=
+MemoryLow=
+MemoryMax=
+MemorySwapMax=
+MessageQueueMaxMessages=
+MessageQueueMessageSize=
+MountAPIVFS=
+NoDelay=
+NoNewPrivileges=
+NonBlocking=
+NotifyAccess=
+OnActiveSec=
+OnBootSec=
+OnCalendar=
+OnFailure=
+OnFailureJobMode=
+OnStartupSec=
+OnUnitActiveSec=
+OnUnitInactiveSec=
+Options=
+PAMName=
+PIDFile=
+PartOf=
+PassCredentials=
+PassSecurity=
+PathChanged=
+PathExists=
+PathExistsGlob=
+PathModified=
+PermissionsStartOnly=
+Persistent=
+PipeSize=
+Priority=
+PropagatesReloadTo=
+RandomizedDelaySec=
+RebootArgument=
+ReceiveBuffer=
+RefuseManualStart=
+RefuseManualStop=
+ReloadPropagatedFrom=
+RemainAfterElapse=
+RemainAfterExit=
+RemoveOnStop=
+RequiredBy=
+Requires=
+RequiresMountsFor=
+Requisite=
+Restart=
+RestartForceExitStatus=
+RestartPreventExitStatus=
+RestartSec=
+ReusePort=
+RootDirectory=
+RootDirectoryStartOnly=
+RootImage=
+RuntimeMaxSec=
+SELinuxContextFromNet=
+SecureBits=
+SendBuffer=
+SendSIGHUP=
+SendSIGKILL=
+Service=
+Slice=
+SloppyOptions=
+SmackLabel=
+SmackLabelIPIn=
+SmackLabelIPOut=
+SocketGroup=
+SocketMode=
+SocketProtocol=
+SocketUser=
+Sockets=
+SourcePath=
+StartLimitAction=
+StartLimitBurst=
+StartLimitIntervalSec=
+StartupBlockIOWeight=
+StartupCPUShares=
+StartupCPUWeight=
+StartupIOWeight=
+StopWhenUnneeded=
+SuccessAction=
+SuccessExitStatus=
+SupplementaryGroups=
+Symlinks=
+TCPCongestion=
+TasksAccounting=
+TasksMax=
+TimeoutIdleSec=
+TimeoutSec=
+TimeoutStartSec=
+TimeoutStopSec=
+Transparent=
+TriggerLimitBurst=
+TriggerLimitIntervalSec=
+Type=
+USBFunctionDescriptors=
+USBFunctionStrings=
+Unit=
+User=
+WakeSystem=
+WantedBy=
+Wants=
+WatchdogSec=
+What=
+Where=
+WorkingDirectory=
+Writable=
+fsck.mode=
+fsck.repair=
+fstab=
+locale.LANG=
+locale.LANGUAGE=
+locale.LC_ADDRESS=
+locale.LC_COLLATE=
+locale.LC_CTYPE=
+locale.LC_IDENTIFICATION=
+locale.LC_MEASUREMENT=
+locale.LC_MESSAGES=
+locale.LC_MONETARY=
+locale.LC_NAME=
+locale.LC_NUMERIC=
+locale.LC_PAPER=
+locale.LC_TELEPHONE=
+locale.LC_TIME=
+luks.crypttab=
+luks.key=
+luks.name=
+luks.options=
+luks.uuid=
+luks=
+modules_load=
+mount.usr=
+mount.usrflags=
+mount.usrfstype=
+net.ifnames=
+plymouth.enable=
+quotacheck.mode=
+rd.fstab=
+rd.luks.crypttab=
+rd.luks.key=
+rd.luks.name=
+rd.luks.options=
+rd.luks.uuid=
+rd.luks=
+rd.modules_load=
+rd.systemd.gpt_auto=
+rd.systemd.unit=
+rd.systemd.verity=
+rd.udev.children_max=
+rd.udev.event_timeout=
+rd.udev.exec_delay=
+rd.udev.log_priority=
+resume=
+root=
+rootflags=
+rootfstype=
+roothash=
+systemd.default_standard_error=
+systemd.default_standard_output=
+systemd.default_timeout_start_sec=
+systemd.firstboot=
+systemd.gpt_auto=
+systemd.journald.forward_to_console=
+systemd.journald.forward_to_kmsg=
+systemd.journald.forward_to_syslog=
+systemd.journald.forward_to_wall=
+systemd.log_level=
+systemd.log_location=
+systemd.log_target=
+systemd.machine_id=
+systemd.mask=
+systemd.restore_state=
+systemd.service_watchdogs=
+systemd.setenv=
+systemd.unit=
+systemd.verity=
+systemd.verity_root_data=
+systemd.verity_root_hash=
+systemd.volatile=
+systemd.wants=
+systemd.watchdog_device=
+udev.children_max=
+udev.event_timeout=
+udev.exec_delay=
+udev.log_priority=
+vconsole.font=
+vconsole.font_map=
+vconsole.font_unimap=
+vconsole.keymap=
+vconsole.keymap_toggle=
+ID_MODEL=
+ID_MODEL_FROM_DATABASE=
+SYSTEMD_ALIAS=
+SYSTEMD_MOUNT_OPTIONS=
+SYSTEMD_MOUNT_WHERE=
+SYSTEMD_READY=
+SYSTEMD_USER_WANTS=
+SYSTEMD_WANTS=
+link_priority=
+static_node=
+string_escape=
+ARP=
+ARPAllTargets=
+ARPIPTargets=
+ARPIntervalSec=
+ARPValidate=
+ActiveSlave=
+AdSelect=
+Address=
+AddressAutoconfiguration=
+AgeingTimeSec=
+Alias=
+AllSlavesActive=
+AllowLocalRemote=
+AllowPortToBeRoot=
+AllowedIPs=
+Anonymize=
+Architecture=
+AutoJoin=
+AutoNegotiation=
+BindCarrier=
+BitsPerSecond=
+Bond=
+Bridge=
+Broadcast=
+Cache=
+ClientIdentifier=
+ConfigureWithoutCarrier=
+CopyDSCP=
+Cost=
+CriticalConnection=
+DHCP=
+DHCPServer=
+DNS=
+DNSLifetimeSec=
+DNSSEC=
+DNSSECNegativeTrustAnchors=
+DNSStubListener=
+DUIDRawData=
+DUIDType=
+DefaultLeaseTimeSec=
+DefaultPVID=
+Description=
+Destination=
+DestinationPort=
+DiscoverPathMTU=
+Domains=
+DownDelaySec=
+Driver=
+Duplex=
+DuplicateAddressDetection=
+EgressUntagged=
+EmitDNS=
+EmitDomains=
+EmitLLDP=
+EmitNTP=
+EmitRouter=
+EmitTimezone=
+EncapsulationLimit=
+Endpoint=
+FDBAgeingSec=
+FailOverMACPolicy=
+FallbackDNS=
+FallbackNTP=
+FastLeave=
+FirewallMark=
+Flags=
+FlowLabel=
+ForwardDelaySec=
+From=
+FwMark=
+GVRP=
+Gateway=
+GatewayOnlink=
+GenericReceiveOffload=
+GenericSegmentationOffload=
+GratuitousARP=
+Group=
+GroupForwardMask=
+GroupPolicyExtension=
+HairPin=
+HelloTimeSec=
+HomeAddress=
+Host=
+Hostname=
+IAID=
+IPForward=
+IPMasquerade=
+IPv4LLRoute=
+IPv4ProxyARP=
+IPv6AcceptRA=
+IPv6DuplicateAddressDetection=
+IPv6FlowLabel=
+IPv6HopLimit=
+IPv6Preference=
+IPv6PrefixDelegation=
+IPv6PrivacyExtensions=
+IPv6ProxyNDP=
+IPv6ProxyNDPAddress=
+IPv6Token=
+Id=
+IncomingInterface=
+Independent=
+InitialAdvertisedReceiveWindow=
+InitialCongestionWindow=
+InputKey=
+KernelCommandLine=
+KernelVersion=
+Key=
+Kind=
+L2MissNotification=
+L3MissNotification=
+LACPTransmitRate=
+LLDP=
+LLMNR=
+Label=
+LargeReceiveOffload=
+LearnPacketIntervalSec=
+LinkLocalAddressing=
+ListenPort=
+Local=
+LooseBinding=
+MACAddress=
+MACAddressPolicy=
+MACVLAN=
+MIIMonitorSec=
+MTUBytes=
+MVRP=
+MacLearning=
+ManageTemporaryAddress=
+Managed=
+MaxAgeSec=
+MaxLeaseTimeSec=
+MaximumFDBEntries=
+Metric=
+MinLinks=
+Mode=
+MultiQueue=
+MulticastDNS=
+MulticastQuerier=
+MulticastSnooping=
+NTP=
+Name=
+NamePolicy=
+OnLink=
+OneQueue=
+OriginalName=
+OtherInformation=
+OutgoingInterface=
+OutputKey=
+PVID=
+PacketInfo=
+PacketsPerSlave=
+Path=
+Peer=
+PersistentKeepalive=
+PollIntervalMaxSec=
+PollIntervalMinSec=
+PoolOffset=
+PoolSize=
+Port=
+PortRange=
+PreferredLifetime=
+PreferredLifetimeSec=
+PreferredSource=
+Prefix=
+PrefixRoute=
+PresharedKey=
+PrimaryReselectPolicy=
+PrimarySlave=
+Priority=
+PrivateKey=
+Protocol=
+PublicKey=
+QuickAck=
+RapidCommit=
+ReduceARPProxy=
+Remote=
+RemoteChecksumRx=
+RemoteChecksumTx=
+ReorderHeader=
+RequestBroadcast=
+RequiredForOnline=
+ResendIGMP=
+RootDistanceMaxSec=
+RouteMetric=
+RouteShortCircuit=
+RouteTable=
+RouterLifetimeSec=
+RouterPreference=
+STP=
+Scope=
+SendHostname=
+Source=
+TCP6SegmentationOffload=
+TCPSegmentationOffload=
+TOS=
+TTL=
+Table=
+Timezone=
+To=
+TransmitHashPolicy=
+Tunnel=
+TxtData=
+TxtText=
+Type=
+TypeOfService=
+UDP6ZeroChecksumRx=
+UDP6ZeroChecksumTx=
+UDPChecksum=
+UDPSegmentationOffload=
+UnicastFlood=
+Unmanaged=
+UpDelaySec=
+UseBPDU=
+UseDNS=
+UseDomains=
+UseHostname=
+UseMTU=
+UseNTP=
+UseRoutes=
+UseTimezone=
+User=
+VLAN=
+VLANFiltering=
+VLANId=
+VNetHeader=
+VRF=
+VXLAN=
+ValidLifetimeSec=
+VendorClassIdentifier=
+Virtualization=
+WakeOnLan=
+Weight=
+CODE_FILE=
+CODE_FUNC=
+CODE_LINE=
+COREDUMP_UNIT=
+COREDUMP_USER_UNIT=
+ERRNO=
+MESSAGE=
+MESSAGE_ID=
+OBJECT_AUDIT_LOGINUID=
+OBJECT_AUDIT_SESSION=
+OBJECT_CMDLINE=
+OBJECT_COMM=
+OBJECT_EXE=
+OBJECT_GID=
+OBJECT_PID=
+OBJECT_SYSTEMD_CGROUP=
+OBJECT_SYSTEMD_OWNER_UID=
+OBJECT_SYSTEMD_SESSION=
+OBJECT_SYSTEMD_UNIT=
+OBJECT_SYSTEMD_USER_UNIT=
+OBJECT_UID=
+PRIORITY=
+SYSLOG_FACILITY=
+SYSLOG_IDENTIFIER=
+SYSLOG_PID=
+_AUDIT_LOGINUID=
+_AUDIT_SESSION=
+_BOOT_ID=
+_CAP_EFFECTIVE=
+_CMDLINE=
+_COMM=
+_EXE=
+_GID=
+_HOSTNAME=
+_KERNEL_DEVICE=
+_KERNEL_SUBSYSTEM=
+_LINE_BREAK=
+_MACHINE_ID=
+_PID=
+_SELINUX_CONTEXT=
+_SOURCE_REALTIME_TIMESTAMP=
+_STREAM_ID=
+_SYSTEMD_CGROUP=
+_SYSTEMD_INVOCATION_ID=
+_SYSTEMD_OWNER_UID=
+_SYSTEMD_SESSION=
+_SYSTEMD_SLICE=
+_SYSTEMD_UNIT=
+_SYSTEMD_USER_UNIT=
+_TRANSPORT=
+_UDEV_DEVLINK=
+_UDEV_DEVNODE=
+_UDEV_SYSNAME=
+_UID=
+__CURSOR=
+__MONOTONIC_TIMESTAMP=
+__REALTIME_TIMESTAMP=
+class=
+type=
+cipher=
+hash=
+header=
+key-slot=
+keyfile-offset=
+keyfile-size=
+offset=
+size=
+skip=
+tcrypt-keyfile=
+timeout=
+tries=
+x-systemd.after=
+x-systemd.before=
+x-systemd.device-timeout=
+x-systemd.idle-timeout=
+x-systemd.mount-timeout=
+x-systemd.requires-mounts-for=
+x-systemd.requires=
+CPUAffinity=
+CapabilityBoundingSet=
+CrashChangeVT=
+CrashReboot=
+CrashShell=
+CtrlAltDelBurstAction=
+DefaultBlockIOAccounting=
+DefaultCPUAccounting=
+DefaultEnvironment=
+DefaultIPAccounting=
+DefaultLimitAS=
+DefaultLimitCORE=
+DefaultLimitCPU=
+DefaultLimitDATA=
+DefaultLimitFSIZE=
+DefaultLimitLOCKS=
+DefaultLimitMEMLOCK=
+DefaultLimitMSGQUEUE=
+DefaultLimitNICE=
+DefaultLimitNOFILE=
+DefaultLimitNPROC=
+DefaultLimitRSS=
+DefaultLimitRTPRIO=
+DefaultLimitRTTIME=
+DefaultLimitSIGPENDING=
+DefaultLimitSTACK=
+DefaultMemoryAccounting=
+DefaultRestartSec=
+DefaultStandardError=
+DefaultStandardOutput=
+DefaultStartLimitBurst=
+DefaultStartLimitIntervalSec=
+DefaultTasksAccounting=
+DefaultTasksMax=
+DefaultTimeoutStartSec=
+DefaultTimeoutStopSec=
+DefaultTimerAccuracySec=
+DumpCore=
+HibernateMode=
+HibernateState=
+HybridSleepMode=
+HybridSleepState=
+JoinControllers=
+LogColor=
+LogLevel=
+LogLocation=
+LogTarget=
+RuntimeWatchdogSec=
+ShowStatus=
+ShutdownWatchdogSec=
+SuspendMode=
+SuspendState=
+SystemCallArchitectures=
+TimerSlackNSec=
+WatchdogDevice=
+-N=
+-c=
+-e=
+-t=
+ANSI_COLOR=
+AppArmorProfile=
+BUG_REPORT_URL=
+BUILD_ID=
+Bind=
+BindReadOnly=
+Boot=
+Bridge=
+CHASSIS=
+CPE_NAME=
+CPUAffinity=
+CPUSchedulingPolicy=
+CPUSchedulingPriority=
+CPUSchedulingResetOnFork=
+CacheDirectory=
+CacheDirectoryMode=
+Capability=
+Compress=
+ConfigurationDirectory=
+ConfigurationDirectoryMode=
+DEPLOYMENT=
+DropCapability=
+Environment=
+EnvironmentFile=
+ExternalSizeMax=
+FONT=
+FONT_MAP=
+FONT_UNIMAP=
+ForwardToConsole=
+ForwardToKMsg=
+ForwardToSyslog=
+ForwardToWall=
+HOME_URL=
+HandleHibernateKey=
+HandleLidSwitch=
+HandleLidSwitchDocked=
+HandleLidSwitchExternalPower=
+HandlePowerKey=
+HandleSuspendKey=
+HibernateKeyIgnoreInhibited=
+HoldoffTimeoutSec=
+ICON_NAME=
+ID=
+ID_LIKE=
+IOSchedulingClass=
+IOSchedulingPriority=
+IPVLAN=
+IdleAction=
+IdleActionSec=
+IgnoreSIGPIPE=
+InaccessiblePaths=
+InhibitDelayMaxSec=
+InhibitorsMax=
+Interface=
+JournalSizeMax=
+KEYMAP=
+KEYMAP_TOGGLE=
+KeepFree=
+KeyringMode=
+KillExcludeUsers=
+KillOnlyUsers=
+KillSignal=
+KillUserProcesses=
+LOCATION=
+LidSwitchIgnoreInhibited=
+LimitAS=
+LimitCORE=
+LimitCPU=
+LimitDATA=
+LimitFSIZE=
+LimitLOCKS=
+LimitMEMLOCK=
+LimitMSGQUEUE=
+LimitNICE=
+LimitNOFILE=
+LimitNPROC=
+LimitRSS=
+LimitRTPRIO=
+LimitRTTIME=
+LimitSIGPENDING=
+LimitSTACK=
+LineMax=
+LockPersonality=
+LogExtraFields=
+LogLevelMax=
+LogsDirectory=
+LogsDirectoryMode=
+MACVLAN=
+MachineID=
+MaxFileSec=
+MaxLevelConsole=
+MaxLevelKMsg=
+MaxLevelStore=
+MaxLevelSyslog=
+MaxLevelWall=
+MaxRetentionSec=
+MaxUse=
+MemoryDenyWriteExecute=
+MountFlags=
+NAME=
+NAutoVTs=
+Nice=
+NoNewPrivileges=
+NotifyReady=
+OOMScoreAdjust=
+Overlay=
+OverlayReadOnly=
+PRETTY_HOSTNAME=
+PRETTY_NAME=
+PRIVACY_POLICY_URL=
+Parameters=
+PassEnvironment=
+Personality=
+PivotRoot=
+Port=
+PowerKeyIgnoreInhibited=
+Private=
+PrivateDevices=
+PrivateNetwork=
+PrivateTmp=
+PrivateUsers=
+PrivateUsersChown=
+ProcessSizeMax=
+ProcessTwo=
+ProtectControlGroups=
+ProtectHome=
+ProtectKernelModules=
+ProtectKernelTunables=
+ProtectSystem=
+RateLimitBurst=
+RateLimitIntervalSec=
+ReadKMsg=
+ReadOnly=
+ReadOnlyPaths=
+ReadWritePaths=
+RemoveIPC=
+ReserveVT=
+RestrictAddressFamilies=
+RestrictNamespaces=
+RestrictRealtime=
+RuntimeDirectory=
+RuntimeDirectoryMode=
+RuntimeDirectoryPreserve=
+RuntimeDirectorySize=
+RuntimeKeepFree=
+RuntimeMaxFileSize=
+RuntimeMaxFiles=
+RuntimeMaxUse=
+SELinuxContext=
+SUPPORT_URL=
+Seal=
+ServerCertificateFile=
+ServerKeyFile=
+SessionsMax=
+SmackProcessLabel=
+SplitMode=
+StandardError=
+StandardInput=
+StandardInputData=
+StandardInputText=
+StandardOutput=
+StateDirectory=
+StateDirectoryMode=
+Storage=
+SuspendKeyIgnoreInhibited=
+SyncIntervalSec=
+SyslogFacility=
+SyslogIdentifier=
+SyslogLevel=
+SyslogLevelPrefix=
+SystemCallArchitectures=
+SystemCallErrorNumber=
+SystemCallFilter=
+SystemKeepFree=
+SystemMaxFileSize=
+SystemMaxFiles=
+SystemMaxUse=
+TTYPath=
+TTYReset=
+TTYVHangup=
+TTYVTDisallocate=
+TemporaryFileSystem=
+TimerSlackNSec=
+TrustedCertificateFile=
+UMask=
+URL=
+UnsetEnvironment=
+User=
+UserTasksMax=
+UtmpIdentifier=
+UtmpMode=
+VARIANT=
+VARIANT_ID=
+VERSION=
+VERSION_CODENAME=
+VERSION_ID=
+VirtualEthernet=
+VirtualEthernetExtra=
+Volatile=
+WorkingDirectory=
+Zone=
diff --git a/test/fuzz-corpus/unit-file/empty.scope b/test/fuzz-corpus/unit-file/empty.scope
new file mode 100644
index 0000000000..8df7245f62
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/empty.scope
@@ -0,0 +1,2 @@
+scope
+[Scope]
diff --git a/test/fuzz-corpus/unit-file/machine.slice b/test/fuzz-corpus/unit-file/machine.slice
new file mode 100644
index 0000000000..bf8c6bfc3e
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/machine.slice
@@ -0,0 +1,14 @@
+slice
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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/test/fuzz-corpus/unit-file/proc-sys-fs-binfmt_misc.automount b/test/fuzz-corpus/unit-file/proc-sys-fs-binfmt_misc.automount
new file mode 100644
index 0000000000..777a123ef4
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/proc-sys-fs-binfmt_misc.automount
@@ -0,0 +1,21 @@
+automount
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Arbitrary Executable File Formats File System Automount Point
+Documentation=https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+DefaultDependencies=no
+Before=sysinit.target
+ConditionPathExists=/proc/sys/fs/binfmt_misc/
+ConditionPathIsReadWrite=/proc/sys/
+
+[Automount]
+Where=/proc/sys/fs/binfmt_misc
diff --git a/test/fuzz-corpus/unit-file/syslog.socket b/test/fuzz-corpus/unit-file/syslog.socket
new file mode 100644
index 0000000000..2eb316fcaa
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/syslog.socket
@@ -0,0 +1,117 @@
+socket
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Syslog Socket
+Documentation=man:systemd.special(7)
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/syslog
+DefaultDependencies=no
+Before=sockets.target
+
+# Don't allow logging until the very end
+Conflicts=shutdown.target
+Before=shutdown.target
+
+# Don't try to activate syslog.service if sysinit.target has failed.
+Conflicts=emergency.service
+Before=emergency.service
+
+[Socket]
+ListenDatagram=/run/systemd/journal/syslog
+SocketMode=0666
+PassCredentials=yes
+PassSecurity=yes
+ReceiveBuffer=8M
+
+# The default syslog implementation should make syslog.service a
+# symlink to itself, so that this socket activates the right actual
+# syslog service.
+#
+# Examples:
+#
+# /etc/systemd/system/syslog.service -> /lib/systemd/system/rsyslog.service
+# /etc/systemd/system/syslog.service -> /lib/systemd/system/syslog-ng.service
+#
+# Best way to achieve that is by adding this to your unit file
+# (i.e. to rsyslog.service or syslog-ng.service):
+#
+# [Install]
+# Alias=syslog.service
+#
+# See https://www.freedesktop.org/wiki/Software/systemd/syslog for details.
+
+[Socket]
+ListenStream=1.2.3.4:1234
+ListenDatagram=1.2.3.4:1234
+ListenSequentialPacket=1.2.3.4:1234
+ListenFIFO=
+ListenSpecial=
+#ListenNetlink=
+ListenMessageQueue=
+ListenUSBFunction=
+SocketProtocol=udplite
+SocketProtocol=sctp
+SocketProtocol=
+BindIPv6Only=false
+Backlog=33
+BindToDevice=eth0
+SocketUser=daemon
+SocketGroup=nobody
+SocketMode=0111
+DirectoryMode=0555
+Accept=true
+Accept=false
+Writable=true
+MaxConnections=11
+MaxConnectionsPerSource=12
+KeepAlive=yes
+KeepAliveTimeSec=12345
+KeepAliveIntervalSec=12345
+KeepAliveProbes=12345
+NoDelay=true
+Priority=0
+DeferAcceptSec=1
+ReceiveBuffer=1G
+SendBuffer=1G
+IPTOS=low-delay
+IPTOS=throughput
+IPTOS=reliability
+IPTOS=low-cost
+IPTOS=
+IPTTL=7
+Mark=123
+ReusePort=true
+SmackLabel=smack-label
+SmackLabelIPIn=smack-label
+SmackLabelIPOut=no idea what to put here
+SELinuxContextFromNet=true
+PipeSize=11111
+MessageQueueMaxMessages=200
+MessageQueueMessageSize=200
+FreeBind=false
+Transparent=true
+Broadcast=true
+PassCredentials=true
+PassSecurity=true
+TCPCongestion=westwood
+TCPCongestion=veno
+TCPCongestion=cubic
+TCPCongestion=lp
+ExecStartPre=/bin/true "arg ' ' "
+ExecStartPost=-!!/bin/false
+ExecStopPre=/bin/true
+ExecStopPost=-!!/bin/false
+TimeoutSec=2343
+Symlinks=a b c d e
+Symlinks=
+Symlinks=/a /b /c /d /e
+FileDescriptorName=name
+TriggerLimitIntervalSec=2343
+TriggerLimitBurst=234
diff --git a/test/fuzz-corpus/unit-file/systemd-ask-password-console.path b/test/fuzz-corpus/unit-file/systemd-ask-password-console.path
new file mode 100644
index 0000000000..3e12c752de
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/systemd-ask-password-console.path
@@ -0,0 +1,22 @@
+path
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Dispatch Password Requests to Console Directory Watch
+Documentation=man:systemd-ask-password-console.service(8)
+DefaultDependencies=no
+Conflicts=shutdown.target
+After=plymouth-start.service
+Before=paths.target shutdown.target cryptsetup.target
+ConditionPathExists=!/run/plymouth/pid
+
+[Path]
+DirectoryNotEmpty=/run/systemd/ask-password
+MakeDirectory=yes
diff --git a/test/fuzz-corpus/unit-file/systemd-machined.service b/test/fuzz-corpus/unit-file/systemd-machined.service
new file mode 100644
index 0000000000..448f062ecf
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/systemd-machined.service
@@ -0,0 +1,34 @@
+service
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=https://www.freedesktop.org/wiki/Software/systemd/machined
+Wants=machine.slice
+After=machine.slice
+RequiresMountsFor=/var/lib/machines
+
+[Service]
+ExecStart=/usr/lib/systemd/systemd-machined
+BusName=org.freedesktop.machine1
+WatchdogSec=3min
+CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD
+MemoryDenyWriteExecute=yes
+RestrictRealtime=yes
+RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+LockPersonality=yes
+IPAddressDeny=any
+
+# Note that machined cannot be placed in a mount namespace, since it
+# needs access to the host's mount namespace in order to implement the
+# "machinectl bind" operation.
diff --git a/test/fuzz-corpus/unit-file/systemd-resolved.service b/test/fuzz-corpus/unit-file/systemd-resolved.service
new file mode 100644
index 0000000000..0854c5f841
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/systemd-resolved.service
@@ -0,0 +1,50 @@
+service
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Network Name Resolution
+Documentation=man:systemd-resolved.service(8)
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/resolved
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
+DefaultDependencies=no
+After=systemd-sysusers.service systemd-networkd.service
+Before=network.target nss-lookup.target shutdown.target
+Conflicts=shutdown.target
+Wants=nss-lookup.target
+
+[Service]
+Type=notify
+Restart=always
+RestartSec=0
+ExecStart=!!/usr/lib/systemd/systemd-resolved
+WatchdogSec=3min
+User=systemd-resolve
+CapabilityBoundingSet=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
+AmbientCapabilities=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
+PrivateTmp=yes
+PrivateDevices=yes
+ProtectSystem=strict
+ProtectHome=yes
+ProtectControlGroups=yes
+ProtectKernelTunables=yes
+ProtectKernelModules=yes
+MemoryDenyWriteExecute=yes
+RestrictRealtime=yes
+RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+LockPersonality=yes
+RuntimeDirectory=systemd/resolve
+RuntimeDirectoryPreserve=yes
+
+[Install]
+WantedBy=multi-user.target
+Alias=dbus-org.freedesktop.resolve1.service
diff --git a/test/fuzz-corpus/unit-file/systemd-tmpfiles-clean.timer b/test/fuzz-corpus/unit-file/systemd-tmpfiles-clean.timer
new file mode 100644
index 0000000000..7db361cd69
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/systemd-tmpfiles-clean.timer
@@ -0,0 +1,40 @@
+timer
+# SPDX-License-Identifier: LGPL-2.1+
+[Unit]
+Description=Daily Cleanup of Temporary Directories
+Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
+
+[Timer]
+OnBootSec=15min
+OnUnitActiveSec=1d
+OnBootSec=1s
+OnStartupSec=234
+OnUnitActiveSec=2y
+OnUnitInactiveSec=23434
+OnCalendar=minutely
+OnCalendar=*-*-* *:*:00
+OnCalendar=hourly
+OnCalendar=*-*-* *:00:00
+OnCalendar=daily
+OnCalendar=*-*-* 00:00:00
+OnCalendar=monthly
+OnCalendar=*-*-01 00:00:00
+OnCalendar=weekly
+OnCalendar=Mon *-*-* 00:00:00
+OnCalendar=yearly
+OnCalendar=*-01-01 00:00:00
+OnCalendar=quarterly
+OnCalendar=*-01,04,07,10-01 00:00:00
+OnCalendar=semiannually
+OnCalendar=*-01,07-01 00:00:00
+OnCalendar=Fri 2012-11-23 11:12:13
+
+Persistent=true
+AccuracySec=24h
+RandomizedDelaySec=234234234
+
+Persistent=no
+Unit=foo.service
+
+WakeSystem=false
+RemainAfterElapse=true
diff --git a/test/fuzz-corpus/unit-file/timers.target b/test/fuzz-corpus/unit-file/timers.target
new file mode 100644
index 0000000000..171226c680
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/timers.target
@@ -0,0 +1,16 @@
+target
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Timers
+Documentation=man:systemd.special(7)
+
+DefaultDependencies=no
+Conflicts=shutdown.target
diff --git a/test/fuzz-corpus/unit-file/var-lib-machines.mount b/test/fuzz-corpus/unit-file/var-lib-machines.mount
new file mode 100644
index 0000000000..9c257d1191
--- /dev/null
+++ b/test/fuzz-corpus/unit-file/var-lib-machines.mount
@@ -0,0 +1,19 @@
+mount
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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 Storage
+ConditionPathExists=/var/lib/machines.raw
+
+[Mount]
+What=/var/lib/machines.raw
+Where=/var/lib/machines
+Type=btrfs
+Options=loop
diff --git a/test/fuzz-regressions/.gitattributes b/test/fuzz-regressions/.gitattributes
new file mode 100644
index 0000000000..7b1b3e1835
--- /dev/null
+++ b/test/fuzz-regressions/.gitattributes
@@ -0,0 +1 @@
+/*/* -whitespace
diff --git a/test/fuzz-regressions/address/fuzz-dns-packet/issue-7888 b/test/fuzz-regressions/fuzz-dns-packet/issue-7888
index 19e7eedf51..19e7eedf51 100644
--- a/test/fuzz-regressions/address/fuzz-dns-packet/issue-7888
+++ b/test/fuzz-regressions/fuzz-dns-packet/issue-7888
Binary files differ
diff --git a/test/fuzz-regressions/address/fuzz-dns-packet/oss-fuzz-5465 b/test/fuzz-regressions/fuzz-dns-packet/oss-fuzz-5465
index ccd8a4fd6b..ccd8a4fd6b 100644
--- a/test/fuzz-regressions/address/fuzz-dns-packet/oss-fuzz-5465
+++ b/test/fuzz-regressions/fuzz-dns-packet/oss-fuzz-5465
Binary files differ
diff --git a/test/fuzz-regressions/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76 b/test/fuzz-regressions/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76
new file mode 100644
index 0000000000..e6a7316805
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76
Binary files differ
diff --git a/test/fuzz-regressions/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 b/test/fuzz-regressions/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45
new file mode 100644
index 0000000000..535d49ea7a
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45
Binary files differ
diff --git a/test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8659 b/test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8659
new file mode 100644
index 0000000000..acc6a0f5e1
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8659
@@ -0,0 +1,8 @@
+ =
+__REALTIME_TIMESTAMP= 404101101501873
+ =
+MESSAGE= aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa__MONOTONIaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaATA=00000000000000000000000000000000000000000000000000000000000000000000000000000006
+
+__CURSOR=IMESTAMP=1404101101483523
+DA0000000000000000000000000000000000000009
+
diff --git a/test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8686 b/test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8686
new file mode 100644
index 0000000000..7c73c8cd9b
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-journal-remote/oss-fuzz-8686
@@ -0,0 +1,6 @@
+__REALTIME_TIMESTAMP= 6
+SYSLOG_IDENTIFIER=
+MESSAGE= ᅟ
+SYSLOG_PID=
+
+ \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6884 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6884
new file mode 100644
index 0000000000..00d105ade5
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6884
@@ -0,0 +1,3 @@
+socket
+[Socket]
+ListenNetlink= \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6885 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6885
new file mode 100644
index 0000000000..1859136fdc
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6885
@@ -0,0 +1,3 @@
+service
+[Service]
+DeviceAllow=%D \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6886 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6886
new file mode 100644
index 0000000000..1fbe5ffd99
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6886
@@ -0,0 +1,3 @@
+timer
+[Timer]
+OnCalendar=@88588582097858858 \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6892 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6892
new file mode 100644
index 0000000000..31f746d034
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6892
@@ -0,0 +1,3 @@
+service
+[Service]
+USBFunctionStrings=/ \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897
new file mode 100644
index 0000000000..742fd9bfeb
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897
@@ -0,0 +1,4 @@
+service
+[Service]
+Slice=%H.slice
+TemporaryFileSystem=%c \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897-evverx b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897-evverx
new file mode 100644
index 0000000000..126678e76c
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6897-evverx
@@ -0,0 +1,4 @@
+service
+[Service]
+Slice=abc-def.slice
+TemporaryFileSystem=%c
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6908 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6908
new file mode 100644
index 0000000000..8f2404b136
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6908
@@ -0,0 +1,3 @@
+socket
+[Socket]
+IOSchedulingClass=531473 \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6917 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6917
new file mode 100644
index 0000000000..9a79cf00b7
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6917
@@ -0,0 +1,4 @@
+timer
+ [Timer]
+ =
+OnCalendar=*-02 9,04,40,04,4,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,0,04,4,40,300,0,04,4,40,04,4..0,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,65535,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,1..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,0440,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,0,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04 \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977
new file mode 100644
index 0000000000..3d844e6f08
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977
@@ -0,0 +1,3 @@
+swap
+[Unit]
+SourcePath=2h=s=%ps=%pwh=s=Sous=%ps=%pwh=s=%ps=%pw%pours=%ps=%pw%pours=%ps=%pwaa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pwaa[Unt=%p=pours=%ps=%pwh=s=%ps=%pw%pours=%ps=%pwaa[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePanh=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%poh=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePpours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pourw=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=Aaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977-unminimized b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977-unminimized
new file mode 100644
index 0000000000..718f94f0d7
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-6977-unminimized
@@ -0,0 +1,3 @@
+swap
+[Unit]
+Documentation=DH⁦0.i%Haaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaation=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctiocumentation=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=Documentation=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH1.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%H%Hction=DH0.i%HN%H%Hction=DH0.i%H󠁫N%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hctio‭n=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hction=DH0.i%HN%H%Hc \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-7004 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-7004
new file mode 100644
index 0000000000..77a5e5e8d6
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-7004
@@ -0,0 +1,3 @@
+timer
+[Timer]
+OnCalendar=*-31/2147483640 \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8064 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8064
new file mode 100644
index 0000000000..2c6c1eaee7
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8064
@@ -0,0 +1,3 @@
+service
+[Service]
+RestartForceExitStatus=RTMIN+2147483644 \ No newline at end of file
diff --git a/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8827 b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8827
new file mode 100644
index 0000000000..c71b75e134
--- /dev/null
+++ b/test/fuzz-regressions/fuzz-unit-file/oss-fuzz-8827
@@ -0,0 +1,5 @@
+timer
+[Timer]
+OnCalendar=.[ H%LH%L%H%H%L%H%L%LLCL%H%C%L%HeH%CH%H%C%L%H%H%C%H%H%CH%L%H%L%L%%imer
+[Timer]
+OnCalendar=.[ H%LH%L%H%H%L%H%L%LLCL%H%C%L%HeH%CH%H%C%L%HeH%CH%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C \ No newline at end of file
diff --git a/test/fuzz-regressions/meson.build b/test/fuzz-regressions/meson.build
index de69c941ea..3a2c306492 100644
--- a/test/fuzz-regressions/meson.build
+++ b/test/fuzz-regressions/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2018 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/>.
sanitize_address = custom_target(
'sanitize-address-fuzzers',
@@ -24,7 +9,26 @@ sanitize_address = custom_target(
'fuzzers',
'-Db_lundef=false -Db_sanitize=address'])
+sanitizers = [['address', sanitize_address]]
+
fuzz_regression_tests = '''
- address/fuzz-dns-packet/oss-fuzz-5465
- address/fuzz-dns-packet/issue-7888
+ fuzz-dns-packet/issue-7888
+ fuzz-dns-packet/oss-fuzz-5465
+ fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76
+ fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45
+ fuzz-journal-remote/oss-fuzz-8659
+ fuzz-journal-remote/oss-fuzz-8686
+ fuzz-unit-file/oss-fuzz-6884
+ fuzz-unit-file/oss-fuzz-6885
+ fuzz-unit-file/oss-fuzz-6886
+ fuzz-unit-file/oss-fuzz-6892
+ fuzz-unit-file/oss-fuzz-6897
+ fuzz-unit-file/oss-fuzz-6897-evverx
+ fuzz-unit-file/oss-fuzz-6908
+ fuzz-unit-file/oss-fuzz-6917
+ fuzz-unit-file/oss-fuzz-6977
+ fuzz-unit-file/oss-fuzz-6977-unminimized
+ fuzz-unit-file/oss-fuzz-7004
+ fuzz-unit-file/oss-fuzz-8064
+ fuzz-unit-file/oss-fuzz-8827
'''.split()
diff --git a/test/hwdb-test.sh b/test/hwdb-test.sh
index a1f3270b64..05363e9ad6 100755
--- a/test/hwdb-test.sh
+++ b/test/hwdb-test.sh
@@ -6,19 +6,6 @@
#
# (C) 2016 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/>.
set -e
diff --git a/test/meson.build b/test/meson.build
index f86cf388e0..826e684e59 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
test_data_files = '''
a.service
@@ -45,6 +30,7 @@ test_data_files = '''
sockets.target
son.service
sysinit.target
+ test-execute/exec-basic.service
test-execute/exec-ambientcapabilities-merge-nfsnobody.service
test-execute/exec-ambientcapabilities-merge-nobody.service
test-execute/exec-ambientcapabilities-merge.service
@@ -93,6 +79,7 @@ test_data_files = '''
test-execute/exec-personality-s390.service
test-execute/exec-personality-x86-64.service
test-execute/exec-personality-x86.service
+ test-execute/exec-privatedevices-disabled-by-prefix.service
test-execute/exec-privatedevices-no-capability-mknod.service
test-execute/exec-privatedevices-no-capability-sys-rawio.service
test-execute/exec-privatedevices-no.service
@@ -110,6 +97,9 @@ test_data_files = '''
test-execute/exec-readonlypaths-with-bindpaths.service
test-execute/exec-readonlypaths.service
test-execute/exec-readwritepaths-mount-propagation.service
+ test-execute/exec-restrictnamespaces-merge-all.service
+ test-execute/exec-restrictnamespaces-merge-and.service
+ test-execute/exec-restrictnamespaces-merge-or.service
test-execute/exec-restrictnamespaces-mnt-blacklist.service
test-execute/exec-restrictnamespaces-mnt.service
test-execute/exec-restrictnamespaces-no.service
@@ -153,6 +143,7 @@ test_data_files = '''
test-execute/exec-user-nobody.service
test-execute/exec-user.service
test-execute/exec-workingdirectory.service
+ test-execute/exec-workingdirectory-trailing-dot.service
test-path/basic.target
test-path/path-changed.path
test-path/path-changed.service
@@ -171,8 +162,17 @@ test_data_files = '''
test-path/path-unit.path
test-path/paths.target
test-path/sysinit.target
+ test-umount/empty.mountinfo
+ test-umount/example.swaps
+ test-umount/garbled.mountinfo
+ test-umount/rhbug-1554943.mountinfo
testsuite.target
timers.target
+ unit-with-.service.d/20-override.conf
+ unit-with-multiple-.service.d/20-override.conf
+ unit-with-multiple-.service.d/30-override.conf
+ unit-with-multiple-dashes.service
+ unit-with-multiple-dashes.service.d/10-override.conf
unstoppable.service
'''.split()
@@ -229,9 +229,13 @@ custom_target(
output : 'sys',
build_by_default : true)
-udev_test_pl = find_program('udev-test.pl')
-test('udev-test',
- udev_test_pl)
+if perl.found()
+ udev_test_pl = find_program('udev-test.pl')
+ test('udev-test',
+ udev_test_pl)
+else
+ message('Skipping udev-test because perl is not available')
+endif
if conf.get('ENABLE_HWDB') == 1
hwdb_test_sh = find_program('hwdb-test.sh')
diff --git a/test/networkd-test.py b/test/networkd-test.py
index 3f917f0d9c..387cdb6400 100755
--- a/test/networkd-test.py
+++ b/test/networkd-test.py
@@ -15,21 +15,8 @@
# ATTENTION: This uses the *installed* networkd, not the one from the built
# source tree.
#
-# (C) 2015 Canonical Ltd.
+# © 2015 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/>.
import errno
import os
@@ -218,6 +205,29 @@ Priority=0
subprocess.check_call(['systemctl', 'restart', 'systemd-networkd'])
self.assertEqual(self.read_attr('port2', 'brport/priority'), '0')
+ def test_bridge_port_property(self):
+ """Test the "[Bridge]" section keys"""
+ self.assertEqual(self.read_attr('port2', 'brport/priority'), '32')
+ self.write_network_dropin('port2.network', 'property', '''\
+[Bridge]
+UnicastFlood=true
+HairPin=true
+UseBPDU=true
+FastLeave=true
+AllowPortToBeRoot=true
+Cost=555
+Priority=23
+''')
+ subprocess.check_call(['systemctl', 'restart', 'systemd-networkd'])
+
+ self.assertEqual(self.read_attr('port2', 'brport/priority'), '23')
+ self.assertEqual(self.read_attr('port2', 'brport/hairpin_mode'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/path_cost'), '555')
+ self.assertEqual(self.read_attr('port2', 'brport/multicast_fast_leave'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/unicast_flood'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/bpdu_guard'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/root_block'), '1')
+
class ClientTestBase(NetworkdTestingUtilities):
"""Provide common methods for testing networkd against servers."""
diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py
index a245432b62..dfb06d9ed9 100755
--- a/test/rule-syntax-check.py
+++ b/test/rule-syntax-check.py
@@ -3,21 +3,8 @@
#
# Simple udev rules syntax checker
#
-# (C) 2010 Canonical Ltd.
+# © 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/>.
import re
import sys
diff --git a/test/run-integration-tests.sh b/test/run-integration-tests.sh
index 7d70be3fea..94df346c28 100755
--- a/test/run-integration-tests.sh
+++ b/test/run-integration-tests.sh
@@ -11,14 +11,16 @@ ninja -C "$BUILD_DIR"
declare -A results
-RESULT=0
+COUNT=0
FAILURES=0
cd "$(dirname "$0")"
for TEST in TEST-??-* ; do
- echo -e "\n--x-- Starting $TEST --x--"
+ COUNT=$(($COUNT+1))
+
+ echo -e "\n--x-- Running $TEST --x--"
set +e
- make -C "$TEST" "BUILD_DIR=$BUILD_DIR" $args
+ ( set -x ; make -C "$TEST" "BUILD_DIR=$BUILD_DIR" $args )
RESULT=$?
set -e
echo "--x-- Result of $TEST: $RESULT --x--"
@@ -40,9 +42,9 @@ for TEST in ${!results[@]}; do
done | sort
if [ "$FAILURES" -eq 0 ] ; then
- echo -e "\nALL PASSED"
+ echo -e "\nALL $COUNT TESTS PASSED"
else
- echo -e "\nTOTAL FAILURES: $FAILURES"
+ echo -e "\nTOTAL FAILURES: $FAILURES OF $COUNT"
fi
exit "$FAILURES"
diff --git a/test/sys-script.py b/test/sys-script.py
index 468c1dc972..a51112603e 100755
--- a/test/sys-script.py
+++ b/test/sys-script.py
@@ -3,22 +3,8 @@
#
# sys-script.py
#
-# (C) 2017 Canonical Ltd.
+# © 2017 Canonical Ltd.
# Author: Dan Streetman <dan.streetman@canonical.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/>.
-#
import os, sys
import shutil
diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py
index 463ee3c555..abb3116c97 100755
--- a/test/sysv-generator-test.py
+++ b/test/sysv-generator-test.py
@@ -3,21 +3,8 @@
#
# systemd-sysv-generator integration test
#
-# (C) 2015 Canonical Ltd.
+# © 2015 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/>.
import collections
import os
diff --git a/test/test-exec-deserialization.py b/test/test-exec-deserialization.py
index 1b8863746c..a11c5ecbf0 100755
--- a/test/test-exec-deserialization.py
+++ b/test/test-exec-deserialization.py
@@ -1,20 +1,7 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1+
#
-# Copyright 2017 Michal Sekletar <msekleta@redhat.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/>.
+# Copyright © 2017 Michal Sekletar <msekleta@redhat.com>
# ATTENTION: This uses the *installed* systemd, not the one from the built
# source tree.
diff --git a/test/test-execute/exec-basic.service b/test/test-execute/exec-basic.service
new file mode 100644
index 0000000000..456f06951a
--- /dev/null
+++ b/test/test-execute/exec-basic.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Test for basic execution
+
+[Service]
+ExecStart=touch /tmp/a ; /bin/touch /tmp/b ; touch /tmp/c
+ExecStart=test -f /tmp/a
+ExecStart=!test -f /tmp/b
+ExecStart=!!test -f /tmp/c
+ExecStart=+test -f /tmp/c
+ExecStartPost=rm /tmp/a /tmp/b /tmp/c
+
+PrivateTmp=true
+Type=oneshot
diff --git a/test/test-execute/exec-bindpaths.service b/test/test-execute/exec-bindpaths.service
index 7bd8fa7402..edab18bb0f 100644
--- a/test/test-execute/exec-bindpaths.service
+++ b/test/test-execute/exec-bindpaths.service
@@ -4,14 +4,14 @@ Description=Test for BindPaths= and BindReadOnlyPaths=
[Service]
Type=oneshot
# Create a file in /tmp/test-exec-bindpaths
-ExecStart=/bin/sh -c 'touch /tmp/test-exec-bindpaths/thisisasimpletest'
+ExecStart=touch /tmp/test-exec-bindpaths/thisisasimpletest
# Then, the file can be access through /tmp
-ExecStart=/bin/sh -c 'test -f /tmp/thisisasimpletest'
+ExecStart=test -f /tmp/thisisasimpletest
# Also, through /tmp/test-exec-bindreadonlypaths
-ExecStart=/bin/sh -c 'test -f /tmp/test-exec-bindreadonlypaths/thisisasimpletest'
+ExecStart=test -f /tmp/test-exec-bindreadonlypaths/thisisasimpletest
# The file cannot modify through /tmp/test-exec-bindreadonlypaths
ExecStart=/bin/sh -x -c '! touch /tmp/test-exec-bindreadonlypaths/thisisasimpletest'
# Cleanup
-ExecStart=/bin/sh -c 'rm /tmp/thisisasimpletest'
+ExecStart=rm /tmp/thisisasimpletest
BindPaths=/tmp:/tmp/test-exec-bindpaths
BindReadOnlyPaths=/tmp:/tmp/test-exec-bindreadonlypaths
diff --git a/test/test-execute/exec-capabilityboundingset-invert.service b/test/test-execute/exec-capabilityboundingset-invert.service
index fd5d248702..1abe390601 100644
--- a/test/test-execute/exec-capabilityboundingset-invert.service
+++ b/test/test-execute/exec-capabilityboundingset-invert.service
@@ -2,6 +2,6 @@
Description=Test for CapabilityBoundingSet
[Service]
-ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "^Bounding set .*cap_chown"); test -z "$$c"'
+ExecStart=/bin/sh -x -c '! capsh --print | grep "^Bounding set .*cap_chown"'
Type=oneshot
CapabilityBoundingSet=~CAP_CHOWN
diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service
index 83bdfb311a..72e6d7686f 100644
--- a/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service
+++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service
@@ -2,14 +2,14 @@
Description=Test DynamicUser= migrate StateDirectory= (preparation)
[Service]
-ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test ! -L /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test ! -L /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay'
+ExecStart=test -w /var/lib/test-dynamicuser-migrate
+ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test ! -L /var/lib/test-dynamicuser-migrate
+ExecStart=test ! -L /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -d /var/lib/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=touch /var/lib/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay
Type=oneshot
DynamicUser=no
diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service
index 8154922a2f..edb0be7ef8 100644
--- a/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service
+++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service
@@ -1,23 +1,23 @@
[Unit]
-Description=Test DynamicUser= migrate StateDirectory= (preparation)
+Description=Test DynamicUser= migrate StateDirectory=
[Service]
-ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -L /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -L /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -f /var/lib/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay'
-ExecStart=/bin/sh -c 'test -d /var/lib/private/test-dynamicuser-migrate'
-ExecStart=/bin/sh -c 'test -d /var/lib/private/test-dynamicuser-migrate2/hoge'
-ExecStart=/bin/sh -c 'test -f /var/lib/private/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay'
-ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay'
-ExecStart=/bin/sh -c 'touch /var/lib/private/test-dynamicuser-migrate/yay'
-ExecStart=/bin/sh -c 'touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay'
+ExecStart=test -w /var/lib/test-dynamicuser-migrate
+ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -L /var/lib/test-dynamicuser-migrate
+ExecStart=test -L /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -d /var/lib/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -f /var/lib/test-dynamicuser-migrate/yay
+ExecStart=test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=test -d /var/lib/private/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/private/test-dynamicuser-migrate2/hoge
+ExecStart=test -f /var/lib/private/test-dynamicuser-migrate/yay
+ExecStart=test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=touch /var/lib/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=touch /var/lib/private/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay
Type=oneshot
DynamicUser=yes
diff --git a/test/test-execute/exec-dynamicuser-statedir.service b/test/test-execute/exec-dynamicuser-statedir.service
index 5ea6d9da42..f459f3c1eb 100644
--- a/test/test-execute/exec-dynamicuser-statedir.service
+++ b/test/test-execute/exec-dynamicuser-statedir.service
@@ -2,17 +2,17 @@
Description=Test DynamicUser= with StateDirectory=
[Service]
-ExecStart=/bin/sh -c 'test -w /var/lib/waldo'
-ExecStart=/bin/sh -c 'test -w /var/lib/quux/pief'
-ExecStart=/bin/sh -c 'touch /var/lib/waldo/yay'
-ExecStart=/bin/sh -c 'touch /var/lib/quux/pief/yayyay'
-ExecStart=/bin/sh -c 'test -f /var/lib/waldo/yay'
-ExecStart=/bin/sh -c 'test -f /var/lib/quux/pief/yayyay'
-ExecStart=/bin/sh -c 'test -f /var/lib/private/waldo/yay'
-ExecStart=/bin/sh -c 'test -f /var/lib/private/quux/pief/yayyay'
+ExecStart=test -w /var/lib/waldo
+ExecStart=test -w /var/lib/quux/pief
+ExecStart=touch /var/lib/waldo/yay
+ExecStart=touch /var/lib/quux/pief/yayyay
+ExecStart=test -f /var/lib/waldo/yay
+ExecStart=test -f /var/lib/quux/pief/yayyay
+ExecStart=test -f /var/lib/private/waldo/yay
+ExecStart=test -f /var/lib/private/quux/pief/yayyay
# Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates
-ExecStart=/bin/sh -x -c 'test $$(find / -type d -writable 2> /dev/null | egrep -v -e \'^(/var/tmp$$|/tmp$$|/proc/|/dev/mqueue$$|/dev/shm$$|/sys/fs/bpf$$)\' | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo'
+ExecStart=sh -x -c 'test $$(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf \) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo'
Type=oneshot
DynamicUser=yes
diff --git a/test/test-execute/exec-environmentfile.service b/test/test-execute/exec-environmentfile.service
index f6b8462719..9bcb133aec 100644
--- a/test/test-execute/exec-environmentfile.service
+++ b/test/test-execute/exec-environmentfile.service
@@ -2,6 +2,6 @@
Description=Test for EnvironmentFile
[Service]
-ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"'
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
Type=oneshot
EnvironmentFile=/tmp/test-exec_environmentfile.conf
diff --git a/test/test-execute/exec-passenvironment-absent.service b/test/test-execute/exec-passenvironment-absent.service
index 7d5e32a4eb..d257e48cda 100644
--- a/test/test-execute/exec-passenvironment-absent.service
+++ b/test/test-execute/exec-passenvironment-absent.service
@@ -2,6 +2,6 @@
Description=Test for PassEnvironment with variables absent from the execution environment
[Service]
-ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset"'
+ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset" && test "$${VAR5-unset}" = "unset"'
Type=oneshot
-PassEnvironment=VAR1 VAR2 VAR3
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
diff --git a/test/test-execute/exec-passenvironment-empty.service b/test/test-execute/exec-passenvironment-empty.service
index c93c197c10..291259a347 100644
--- a/test/test-execute/exec-passenvironment-empty.service
+++ b/test/test-execute/exec-passenvironment-empty.service
@@ -2,7 +2,7 @@
Description=Test for PassEnvironment and erasing the variable list
[Service]
-ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset"'
+ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset" && test "$${VAR5-unset}" = "unset"'
Type=oneshot
-PassEnvironment=VAR1 VAR2 VAR3
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
PassEnvironment=
diff --git a/test/test-execute/exec-passenvironment-repeated.service b/test/test-execute/exec-passenvironment-repeated.service
index 5e8c56f26a..e88699802f 100644
--- a/test/test-execute/exec-passenvironment-repeated.service
+++ b/test/test-execute/exec-passenvironment-repeated.service
@@ -2,7 +2,9 @@
Description=Test for PassEnvironment with a variable name repeated
[Service]
-ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"'
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
Type=oneshot
PassEnvironment=VAR1 VAR2
PassEnvironment=VAR1 VAR3
+PassEnvironment=VAR1 VAR4
+PassEnvironment=VAR1 VAR5
diff --git a/test/test-execute/exec-passenvironment.service b/test/test-execute/exec-passenvironment.service
index b4a9909682..05c1bdfe88 100644
--- a/test/test-execute/exec-passenvironment.service
+++ b/test/test-execute/exec-passenvironment.service
@@ -2,6 +2,6 @@
Description=Test for PassEnvironment
[Service]
-ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"'
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
Type=oneshot
-PassEnvironment=VAR1 VAR2 VAR3
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
diff --git a/test/test-execute/exec-personality-aarch64.service b/test/test-execute/exec-personality-aarch64.service
index 40b6d95e3a..8511174411 100644
--- a/test/test-execute/exec-personality-aarch64.service
+++ b/test/test-execute/exec-personality-aarch64.service
@@ -1,4 +1,4 @@
-Unit]
+[Unit]
Description=Test for Personality=aarch64
[Service]
diff --git a/test/test-execute/exec-privatedevices-disabled-by-prefix.service b/test/test-execute/exec-privatedevices-disabled-by-prefix.service
new file mode 100644
index 0000000000..19b1da5240
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-disabled-by-prefix.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for PrivateDevices=yes with prefix
+
+[Service]
+ExecStart=/bin/sh -x -c '! test -c /dev/kmsg'
+ExecStart=+/bin/sh -x -c 'test -c /dev/kmsg'
+Type=oneshot
+PrivateDevices=yes
diff --git a/test/test-execute/exec-privatedevices-no.service b/test/test-execute/exec-privatedevices-no.service
index 0285a83ee4..4ddbf189b7 100644
--- a/test/test-execute/exec-privatedevices-no.service
+++ b/test/test-execute/exec-privatedevices-no.service
@@ -1,5 +1,5 @@
[Unit]
-Description=Test for PrivateDev=no
+Description=Test for PrivateDevices=no
[Service]
ExecStart=/bin/sh -x -c 'test -c /dev/kmsg'
diff --git a/test/test-execute/exec-privatedevices-yes.service b/test/test-execute/exec-privatedevices-yes.service
index 094257f414..3516667207 100644
--- a/test/test-execute/exec-privatedevices-yes.service
+++ b/test/test-execute/exec-privatedevices-yes.service
@@ -1,5 +1,5 @@
[Unit]
-Description=Test for PrivateDev=yes
+Description=Test for PrivateDevices=yes
[Service]
ExecStart=/bin/sh -c 'test ! -c /dev/kmsg'
diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service
index 3df543ec93..a38d24912f 100644
--- a/test/test-execute/exec-privatenetwork-yes.service
+++ b/test/test-execute/exec-privatenetwork-yes.service
@@ -2,6 +2,6 @@
Description=Test for PrivateNetwork
[Service]
-ExecStart=/bin/sh -x -c 'i=$$(ip link | grep ": " | grep -v ": lo:"); test -z "$$i"'
+ExecStart=/bin/sh -x -c '! ip link | grep ": " | grep -Ev ": (lo|sit0@.*):"'
Type=oneshot
PrivateNetwork=yes
diff --git a/test/test-execute/exec-restrictnamespaces-merge-all.service b/test/test-execute/exec-restrictnamespaces-merge-all.service
new file mode 100644
index 0000000000..de98cd0a2e
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-merge-all.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test merging RestrictNamespaces= with all flags
+
+[Service]
+RestrictNamespaces=mnt pid cgroup net uts ipc user
+RestrictNamespaces=net
+ExecStart=unshare -m -u -i -n -p -f
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-merge-and.service b/test/test-execute/exec-restrictnamespaces-merge-and.service
new file mode 100644
index 0000000000..6702e6aab2
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-merge-and.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test merging RestrictNamespaces= with AND
+
+[Service]
+RestrictNamespaces=mnt pid
+RestrictNamespaces=~mnt usr
+ExecStart=unshare -p -f
+ExecStart=sh -c '! unshare -m -u -i -n'
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-merge-or.service b/test/test-execute/exec-restrictnamespaces-merge-or.service
new file mode 100644
index 0000000000..a52455204d
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-merge-or.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test merging RestrictNamespaces= with OR
+
+[Service]
+RestrictNamespaces=mnt pid
+RestrictNamespaces=mnt uts
+ExecStart=unshare -m -u -p -f
+ExecStart=sh -c '! unshare -u -i -n'
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-mnt-blacklist.service b/test/test-execute/exec-restrictnamespaces-mnt-blacklist.service
index ab909cbd94..7756a2575e 100644
--- a/test/test-execute/exec-restrictnamespaces-mnt-blacklist.service
+++ b/test/test-execute/exec-restrictnamespaces-mnt-blacklist.service
@@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=~mnt
[Service]
RestrictNamespaces=~mnt
-ExecStart=/bin/sh -x -c 'unshare -m'
+ExecStart=unshare -m
Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-mnt.service b/test/test-execute/exec-restrictnamespaces-mnt.service
index 1aeed72717..2c5b942601 100644
--- a/test/test-execute/exec-restrictnamespaces-mnt.service
+++ b/test/test-execute/exec-restrictnamespaces-mnt.service
@@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=mnt
[Service]
RestrictNamespaces=mnt
-ExecStart=/bin/sh -x -c 'unshare -m'
+ExecStart=unshare -m
Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-no.service b/test/test-execute/exec-restrictnamespaces-no.service
index 33500302d2..5ffe081e45 100644
--- a/test/test-execute/exec-restrictnamespaces-no.service
+++ b/test/test-execute/exec-restrictnamespaces-no.service
@@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=no
[Service]
RestrictNamespaces=no
-ExecStart=/bin/sh -x -c 'unshare -m -u -i -n -p -f'
+ExecStart=unshare -m -u -i -n -p -f
Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-yes.service b/test/test-execute/exec-restrictnamespaces-yes.service
index 3fe70e2bea..8e077ed3a0 100644
--- a/test/test-execute/exec-restrictnamespaces-yes.service
+++ b/test/test-execute/exec-restrictnamespaces-yes.service
@@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=yes
[Service]
RestrictNamespaces=yes
-ExecStart=/bin/sh -x -c 'unshare -m'
+ExecStart=unshare -m
Type=oneshot
diff --git a/test/test-execute/exec-runtimedirectory.service b/test/test-execute/exec-runtimedirectory.service
index d8f242fde2..6a4383110f 100644
--- a/test/test-execute/exec-runtimedirectory.service
+++ b/test/test-execute/exec-runtimedirectory.service
@@ -3,5 +3,7 @@ Description=Test for RuntimeDirectory
[Service]
ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectory'
+ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectory2/hogehoge'
Type=oneshot
RuntimeDirectory=test-exec_runtimedirectory
+RuntimeDirectory=./test-exec_runtimedirectory2///./hogehoge/.
diff --git a/test/test-execute/exec-specifier-interpolation.service b/test/test-execute/exec-specifier-interpolation.service
index 3e62662aa9..f128e3c4b3 100644
--- a/test/test-execute/exec-specifier-interpolation.service
+++ b/test/test-execute/exec-specifier-interpolation.service
@@ -3,4 +3,4 @@ Description=https://github.com/systemd/systemd/issues/2637
[Service]
Type=oneshot
-ExecStart=/bin/sh -x -c "perl -e 'exit(!(qq{%%U} eq qq{\\x25U}))'"
+ExecStart=/bin/sh -x -c "! test -x perl || perl -e 'exit(!(qq{%%U} eq qq{\\x25U}))'"
diff --git a/test/test-execute/exec-specifier.service b/test/test-execute/exec-specifier.service
index 37852390ac..13ba859879 100644
--- a/test/test-execute/exec-specifier.service
+++ b/test/test-execute/exec-specifier.service
@@ -3,22 +3,27 @@ Description=Test for specifiers
[Service]
Type=oneshot
-ExecStart=/usr/bin/test %n = exec-specifier.service
-ExecStart=/usr/bin/test %N = exec-specifier
-ExecStart=/usr/bin/test %p = exec-specifier
-ExecStart=/usr/bin/test %P = exec/specifier
-ExecStart=/usr/bin/test %i = ""
-ExecStart=/usr/bin/test %I = ""
-ExecStart=/usr/bin/test %f = /exec/specifier
-ExecStart=/usr/bin/test %t = /run
-ExecStart=/usr/bin/test %S = /var/lib
-ExecStart=/usr/bin/test %C = /var/cache
-ExecStart=/usr/bin/test %L = /var/log
-ExecStart=/bin/sh -c 'test %u = $$(id -un 0)'
-ExecStart=/usr/bin/test %U = 0
-ExecStart=/bin/sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)
-ExecStart=/bin/sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7)
-ExecStart=/bin/sh -c 'test %m = $$(cat /etc/machine-id)'
-ExecStart=/bin/sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
-ExecStart=/bin/sh -c 'test %H = $$(hostname)'
-ExecStart=/bin/sh -c 'test %v = $$(uname -r)'
+ExecStart=test %n = exec-specifier.service
+ExecStart=test %N = exec-specifier
+ExecStart=test %p = exec-specifier
+ExecStart=test %P = exec/specifier
+ExecStart=test %i = ""
+ExecStart=test %I = ""
+ExecStart=test %j = specifier
+ExecStart=test %J = specifier
+ExecStart=test %f = /exec/specifier
+ExecStart=test %t = /run
+ExecStart=test %S = /var/lib
+ExecStart=test %C = /var/cache
+ExecStart=test %L = /var/log
+ExecStart=test %E = /etc
+ExecStart=test %T = /tmp
+ExecStart=test %V = /var/tmp
+ExecStart=sh -c 'test %u = $$(id -un 0)'
+ExecStart=test %U = 0
+ExecStart=sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)'
+ExecStart=sh -c 'test %s = /bin/sh'
+ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)'
+ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
+ExecStart=sh -c 'test %H = $$(hostname)'
+ExecStart=sh -c 'test %v = $$(uname -r)'
diff --git a/test/test-execute/exec-specifier@.service b/test/test-execute/exec-specifier@.service
index 0015dffca6..174559dbd1 100644
--- a/test/test-execute/exec-specifier@.service
+++ b/test/test-execute/exec-specifier@.service
@@ -3,22 +3,25 @@ Description=Test for specifiers (template unit)
[Service]
Type=oneshot
-ExecStart=/usr/bin/test %n = exec-specifier@foo-bar.service
-ExecStart=/usr/bin/test %N = exec-specifier@foo-bar
-ExecStart=/usr/bin/test %p = exec-specifier
-ExecStart=/usr/bin/test %P = exec/specifier
-ExecStart=/usr/bin/test %i = foo-bar
-ExecStart=/usr/bin/test %I = foo/bar
-ExecStart=/usr/bin/test %f = /foo/bar
-ExecStart=/usr/bin/test %t = /run
-ExecStart=/usr/bin/test %S = /var/lib
-ExecStart=/usr/bin/test %C = /var/cache
-ExecStart=/usr/bin/test %L = /var/log
-ExecStart=/bin/sh -c 'test %u = $$(id -un 0)'
-ExecStart=/usr/bin/test %U = 0
-ExecStart=/bin/sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)
-ExecStart=/bin/sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7)
-ExecStart=/bin/sh -c 'test %m = $$(cat /etc/machine-id)'
-ExecStart=/bin/sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
-ExecStart=/bin/sh -c 'test %H = $$(hostname)'
-ExecStart=/bin/sh -c 'test %v = $$(uname -r)'
+ExecStart=test %n = exec-specifier@foo-bar.service
+ExecStart=test %N = exec-specifier@foo-bar
+ExecStart=test %p = exec-specifier
+ExecStart=test %P = exec/specifier
+ExecStart=test %i = foo-bar
+ExecStart=test %I = foo/bar
+ExecStart=test %j = specifier
+ExecStart=test %J = specifier
+ExecStart=test %f = /foo/bar
+ExecStart=test %t = /run
+ExecStart=test %S = /var/lib
+ExecStart=test %C = /var/cache
+ExecStart=test %L = /var/log
+ExecStart=test %E = /etc
+ExecStart=sh -c 'test %u = $$(id -un 0)'
+ExecStart=test %U = 0
+ExecStart=sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)'
+ExecStart=sh -c 'test %s = /bin/sh'
+ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)'
+ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
+ExecStart=sh -c 'test %H = $$(hostname)'
+ExecStart=sh -c 'test %v = $$(uname -r)'
diff --git a/test/test-execute/exec-temporaryfilesystem-rw.service b/test/test-execute/exec-temporaryfilesystem-rw.service
index fc02ceab1c..379ad066fb 100644
--- a/test/test-execute/exec-temporaryfilesystem-rw.service
+++ b/test/test-execute/exec-temporaryfilesystem-rw.service
@@ -5,28 +5,28 @@ Description=Test for TemporaryFileSystem
Type=oneshot
# Check directories exist
-ExecStart=/bin/sh -c 'test -d /var/test-exec-temporaryfilesystem/rw && test -d /var/test-exec-temporaryfilesystem/ro'
+ExecStart=test -d /var/test-exec-temporaryfilesystem/rw -a -d /var/test-exec-temporaryfilesystem/ro
# Check TemporaryFileSystem= are empty
-ExecStart=/bin/sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
+ExecStart=sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
# Create a file in /var
-ExecStart=/bin/sh -c 'touch /var/hoge'
+ExecStart=touch /var/hoge
# Create a file in /var/test-exec-temporaryfilesystem/rw
-ExecStart=/bin/sh -c 'touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem'
+ExecStart=touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem
# Then, the file can be access through /tmp
-ExecStart=/bin/sh -c 'test -f /tmp/thisisasimpletest-temporaryfilesystem'
+ExecStart=test -f /tmp/thisisasimpletest-temporaryfilesystem
# Also, through /var/test-exec-temporaryfilesystem/ro
-ExecStart=/bin/sh -c 'test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
+ExecStart=test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem
# The file cannot modify through /var/test-exec-temporaryfilesystem/ro
-ExecStart=/bin/sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
+ExecStart=sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
# Cleanup
-ExecStart=/bin/sh -c 'rm /tmp/thisisasimpletest-temporaryfilesystem'
+ExecStart=rm /tmp/thisisasimpletest-temporaryfilesystem
TemporaryFileSystem=/var
BindPaths=/tmp:/var/test-exec-temporaryfilesystem/rw
diff --git a/test/test-execute/exec-workingdirectory-trailing-dot.service b/test/test-execute/exec-workingdirectory-trailing-dot.service
new file mode 100644
index 0000000000..5c807b3172
--- /dev/null
+++ b/test/test-execute/exec-workingdirectory-trailing-dot.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for WorkingDirectory with trailing dot
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$PWD" = "/tmp/test-exec_workingdirectory"'
+Type=oneshot
+WorkingDirectory=/tmp///./test-exec_workingdirectory/.
diff --git a/test/test-functions b/test/test-functions
index 17e83ccf3f..e69420aeca 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -4,9 +4,9 @@
PATH=/sbin:/bin:/usr/sbin:/usr/bin
export PATH
-LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || "$ID_LIKE" = "debian" ]] && echo yes || true)
-LOOKS_LIKE_ARCH=$(source /etc/os-release && [[ "$ID" = "arch" ]] && echo yes || true)
-LOOKS_LIKE_SUSE=$(source /etc/os-release && [[ "$ID_LIKE" = "suse" ]] && echo yes || true)
+LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || true)
+LOOKS_LIKE_ARCH=$(source /etc/os-release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || true)
+LOOKS_LIKE_SUSE=$(source /etc/os-release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || true)
KERNEL_VER=${KERNEL_VER-$(uname -r)}
KERNEL_MODS="/lib/modules/$KERNEL_VER/"
QEMU_TIMEOUT="${QEMU_TIMEOUT:-infinity}"
@@ -29,9 +29,12 @@ STATEFILE="$STATEDIR/.testdir"
TESTLOG="$STATEDIR/test.log"
function find_qemu_bin() {
- # SUSE and Red Hat call the binary qemu-kvm
- # Debian and Gentoo call it kvm
- [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a kvm qemu-kvm 2>/dev/null | grep '^/' -m1)
+ # SUSE and Red Hat call the binary qemu-kvm. Debian and Gentoo call it kvm.
+ # Either way, only use this version if we aren't running in KVM, because
+ # nested KVM is flaky still.
+ if [ `systemd-detect-virt -v` != kvm ] ; then
+ [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a kvm qemu-kvm 2>/dev/null | grep '^/' -m1)
+ fi
[ "$ARCH" ] || ARCH=$(uname -m)
case $ARCH in
@@ -121,6 +124,7 @@ loglevel=2 \
init=$ROOTLIBDIR/systemd \
console=ttyS0 \
selinux=0 \
+printk.devkmsg=on \
$_cgroup_args \
$KERNEL_APPEND \
"
@@ -137,7 +141,8 @@ $KERNEL_APPEND \
QEMU_OPTIONS="$QEMU_OPTIONS -initrd $INITRD"
fi
- if [ -c /dev/kvm ]; then
+ # Let's use KVM if it is available, but let's avoid using nested KVM as that is still flaky
+ if [ -c /dev/kvm -a `systemd-detect-virt -v` != kvm ]; then
QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host"
fi
@@ -365,6 +370,8 @@ create_empty_image() {
,
EOF
+ udevadm settle
+
local _label="-L systemd"
# mkfs.reiserfs doesn't know -L. so, use --label instead
[[ "$FSTYPE" == "reiserfs" ]] && _label="--label systemd"
diff --git a/test/test-umount/empty.mountinfo b/test/test-umount/empty.mountinfo
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/test-umount/empty.mountinfo
diff --git a/test/test-umount/example.swaps b/test/test-umount/example.swaps
new file mode 100644
index 0000000000..9de4e3e79f
--- /dev/null
+++ b/test/test-umount/example.swaps
@@ -0,0 +1,4 @@
+Filename Type Size Used Priority
+/dev/dm-2 partition 8151036 2283436 -2
+/some/swapfile file 111 111 0
+/some/swapfile2 (deleted) file 111 111 0
diff --git a/test/test-umount/garbled.mountinfo b/test/test-umount/garbled.mountinfo
new file mode 100644
index 0000000000..5f28aea409
--- /dev/null
+++ b/test/test-umount/garbled.mountinfo
@@ -0,0 +1,5 @@
+18 63 1000999:110999 / /sys rw,nosuid,nodev,noexec,relatime shared:2 - sysfs sysfs rw
+44 44
+asdfasdf asdfasdf asdf asdfasdfasdf
+asdfsadfasd
+95 63 8:1 / /one-good-entry rw,relatime shared:34 - ext4 /dev/sda1 rw,data=ordered
diff --git a/test/test-umount/rhbug-1554943.mountinfo b/test/test-umount/rhbug-1554943.mountinfo
new file mode 100644
index 0000000000..d8bdf35862
--- /dev/null
+++ b/test/test-umount/rhbug-1554943.mountinfo
@@ -0,0 +1,47 @@
+18 63 0:18 / /sys rw,nosuid,nodev,noexec,relatime shared:2 - sysfs sysfs rw
+19 63 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:23 - proc proc rw
+20 63 0:6 / /dev rw,nosuid shared:19 - devtmpfs devtmpfs rw,size=3549752k,nr_inodes=887438,mode=755
+21 18 0:7 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:3 - securityfs securityfs rw
+22 20 0:19 / /dev/shm rw,nosuid,nodev shared:20 - tmpfs tmpfs rw
+23 20 0:20 / /dev/pts rw,nosuid,noexec,relatime shared:21 - devpts devpts rw,gid=5,mode=620,ptmxmode=000
+24 63 0:21 / /run rw,nosuid,nodev shared:22 - tmpfs tmpfs rw,mode=755
+25 18 0:22 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,mode=755
+26 25 0:23 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 cgroup rw
+27 25 0:24 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:6 - cgroup cgroup rw,xattr,name=systemd
+28 18 0:25 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:17 - pstore pstore rw
+29 25 0:26 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup rw,cpu,cpuacct
+30 25 0:27 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:8 - cgroup cgroup rw,perf_event
+31 25 0:28 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:9 - cgroup cgroup rw,freezer
+32 25 0:29 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,hugetlb
+33 25 0:30 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,cpuset
+34 25 0:31 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,net_cls,net_prio
+35 25 0:32 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,memory
+36 25 0:33 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,pids
+37 25 0:34 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,blkio
+38 25 0:35 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,devices
+61 18 0:36 / /sys/kernel/config rw,relatime shared:18 - configfs configfs rw
+63 0 8:17 / / rw,relatime shared:1 - ext4 /dev/sdb1 rw,lazytime,commit=30,inode_readahead_blks=16
+39 18 0:8 / /sys/kernel/debug rw,relatime shared:24 - debugfs debugfs rw
+40 20 0:37 / /dev/hugepages rw,relatime shared:25 - hugetlbfs hugetlbfs rw,pagesize=2M
+41 19 0:38 / /proc/sys/fs/binfmt_misc rw,relatime shared:26 - autofs systemd-1 rw,fd=32,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=14807
+42 20 0:17 / /dev/mqueue rw,relatime shared:27 - mqueue mqueue rw
+43 63 0:39 / /var/www/sessiondata rw,nosuid,noexec,noatime shared:28 - tmpfs tmpfs rw,size=4194304k
+75 63 0:40 / /usr/share/mysql-test/var rw,noatime shared:29 - tmpfs tmpfs rw,size=4194304k,mode=750,uid=27,gid=27
+77 63 8:33 / /Volumes/dune rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16
+79 63 8:33 /builduser /home/builduser rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16
+81 77 0:41 / /Volumes/dune/mysql_data/autotest rw,nosuid,noexec,noatime shared:31 - tmpfs tmpfs rw,size=4194304k,mode=700,uid=27,gid=27
+83 63 8:33 /.tmp /var/tmp rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16
+85 77 0:42 / /Volumes/dune/www-servers/cms/cms/temp rw,nosuid,noexec,noatime shared:32 - tmpfs tmpfs rw,size=4194304k,mode=770,uid=48,gid=48
+87 77 8:33 /buildserver/autotest /Volumes/dune/www-servers/autotest rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16
+89 63 8:33 /.tmp /tmp rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16
+91 77 0:43 / /Volumes/dune/www-servers/cms/cms/logs rw,nosuid,noexec,noatime shared:33 - tmpfs tmpfs rw,size=4194304k,mode=770,uid=48,gid=48
+93 63 8:33 /www-servers/cms /usr/local/sftp-homes/flow/cms rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16
+95 63 8:1 / /boot rw,relatime shared:34 - ext4 /dev/sda1 rw,data=ordered
+97 79 0:44 / /home/builduser/rpmbuild/PHP-PGO/logs rw,nosuid,noatime shared:35 - tmpfs tmpfs rw,size=4194304k,mode=770,uid=5000,gid=5000
+98 77 0:44 / /Volumes/dune/builduser/rpmbuild/PHP-PGO/logs rw,nosuid,noatime shared:35 - tmpfs tmpfs rw,size=4194304k,mode=770,uid=5000,gid=5000
+101 63 9:0 / /mnt/raid10 rw,relatime shared:36 - ext4 /dev/md0 rw,lazytime,commit=30,stripe=128,inode_readahead_blks=16
+558 24 0:52 / /run/user/48 rw,nosuid,nodev,relatime shared:83 - tmpfs tmpfs rw,size=711220k,mode=700,uid=48,gid=48
+588 24 0:53 / /run/user/5000 rw,nosuid,nodev,relatime shared:135 - tmpfs tmpfs rw,size=711220k,mode=700,uid=5000,gid=5000
+613 24 0:54 / /run/user/4503 rw,nosuid,nodev,relatime shared:85 - tmpfs tmpfs rw,size=711220k,mode=700,uid=4503,gid=4503
+653 24 0:45 / /run/user/4500 rw,nosuid,nodev,relatime shared:87 - tmpfs tmpfs rw,size=711220k,mode=700,uid=4500,gid=48
+699 24 0:55 / /run/user/0 rw,nosuid,nodev,relatime shared:89 - tmpfs tmpfs rw,size=711220k,mode=700
diff --git a/test/udev-test.pl b/test/udev-test.pl
index 9e7cc94638..0433629c7c 100755
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -14,8 +14,7 @@
# After creation and removal the result is checked against the
# expected value and the result is printed.
#
-# Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
-# Copyright (C) 2004 Leann Ogasawara <ogasawara@osdl.org>
+# Copyright © 2004 Leann Ogasawara <ogasawara@osdl.org>
use warnings;
use strict;
diff --git a/test/unit-.service.d/10-override.conf b/test/unit-.service.d/10-override.conf
new file mode 100644
index 0000000000..916737d415
--- /dev/null
+++ b/test/unit-.service.d/10-override.conf
@@ -0,0 +1,2 @@
+[Unit]
+Description=override0
diff --git a/test/unit-with-.service.d/20-override.conf b/test/unit-with-.service.d/20-override.conf
new file mode 100644
index 0000000000..c6c2438f73
--- /dev/null
+++ b/test/unit-with-.service.d/20-override.conf
@@ -0,0 +1,2 @@
+[Unit]
+Documentation=man:override1
diff --git a/test/unit-with-multiple-.service.d/20-override.conf b/test/unit-with-multiple-.service.d/20-override.conf
new file mode 100644
index 0000000000..62fafd2e3b
--- /dev/null
+++ b/test/unit-with-multiple-.service.d/20-override.conf
@@ -0,0 +1,2 @@
+[Unit]
+Documentation=man:override2
diff --git a/test/unit-with-multiple-.service.d/30-override.conf b/test/unit-with-multiple-.service.d/30-override.conf
new file mode 100644
index 0000000000..b9616da8a8
--- /dev/null
+++ b/test/unit-with-multiple-.service.d/30-override.conf
@@ -0,0 +1,2 @@
+[Unit]
+Documentation=man:override3
diff --git a/test/unit-with-multiple-dashes.service b/test/unit-with-multiple-dashes.service
new file mode 100644
index 0000000000..b38b3604b8
--- /dev/null
+++ b/test/unit-with-multiple-dashes.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=A unit with multiple dashes
+Documentation=man:test
+
+[Service]
+ExecStart=/bin/true
diff --git a/test/unit-with-multiple-dashes.service.d/10-override.conf b/test/unit-with-multiple-dashes.service.d/10-override.conf
new file mode 100644
index 0000000000..982c3621a6
--- /dev/null
+++ b/test/unit-with-multiple-dashes.service.d/10-override.conf
@@ -0,0 +1,2 @@
+[Unit]
+Description=override4
diff --git a/tmpfiles.d/meson.build b/tmpfiles.d/meson.build
index 37a8dfea2d..35eea2be5c 100644
--- a/tmpfiles.d/meson.build
+++ b/tmpfiles.d/meson.build
@@ -1,26 +1,12 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
enable_tmpfiles = conf.get('ENABLE_TMPFILES') == 1
tmpfiles = [['home.conf', ''],
['journal-nocow.conf', ''],
['systemd-nologin.conf', ''],
- ['systemd-nspawn.conf', ''],
+ ['systemd-nspawn.conf', 'ENABLE_MACHINED'],
+ ['portables.conf', 'ENABLE_PORTABLED'],
['tmp.conf', ''],
['x11.conf', ''],
['legacy.conf', 'HAVE_SYSV_COMPAT'],
@@ -50,7 +36,7 @@ foreach pair : m4_files
'tmpfiles.d_' + pair[0],
input : pair[0] + '.m4',
output: pair[0],
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : true,
install_dir : tmpfilesdir)
diff --git a/tmpfiles.d/portables.conf b/tmpfiles.d/portables.conf
new file mode 100644
index 0000000000..b8ddf7f4b7
--- /dev/null
+++ b/tmpfiles.d/portables.conf
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: LGPL-2.1+
+# See tmpfiles.d(5) for details
+
+Q /var/lib/portables 0700
diff --git a/tmpfiles.d/systemd.conf.m4 b/tmpfiles.d/systemd.conf.m4
index 76e3829ab2..0992f74209 100644
--- a/tmpfiles.d/systemd.conf.m4
+++ b/tmpfiles.d/systemd.conf.m4
@@ -17,9 +17,9 @@ d /run/systemd/users 0755 root root -
d /run/systemd/machines 0755 root root -
d /run/systemd/shutdown 0755 root root -
m4_ifdef(`ENABLE_NETWORKD',
-d /run/systemd/netif 0755 systemd-network systemd-network -
-d /run/systemd/netif/links 0755 systemd-network systemd-network -
-d /run/systemd/netif/leases 0755 systemd-network systemd-network -
+d /run/systemd/netif - - - -
+d /run/systemd/netif/links - - - -
+d /run/systemd/netif/leases - - - -
)m4_dnl
d /run/log 0755 root root -
@@ -71,3 +71,7 @@ a+ /var/log/journal/%m/system.journal - - - - group:wheel:r--
d /var/lib/systemd 0755 root root -
d /var/lib/systemd/coredump 0755 root root 3d
+
+d /var/lib/private 0700 root root -
+d /var/log/private 0700 root root -
+d /var/cache/private 0700 root root -
diff --git a/tools/catalog-report.py b/tools/catalog-report.py
index 426ea0d891..b65869d02b 100755
--- a/tools/catalog-report.py
+++ b/tools/catalog-report.py
@@ -2,10 +2,7 @@
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: MIT
#
-# This file is part of systemd. It is distrubuted under the MIT license, see
-# below.
-#
-# Copyright 2016 Zbigniew Jędrzejewski-Szmek
+# This file is distributed under the MIT license, see below.
#
# The MIT License (MIT)
#
diff --git a/scripts/coverity.sh b/tools/coverity.sh
index 3e8d874728..561d127d1e 100755
--- a/scripts/coverity.sh
+++ b/tools/coverity.sh
@@ -1,5 +1,10 @@
#!/bin/env bash
+# The official unmodified version of the script can be found at
+# https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh
+
+set -e
+
# Declare build command
COVERITY_SCAN_BUILD_COMMAND="ninja -C cov-build"
@@ -135,8 +140,12 @@ _upload()
--form version=$SHA \
--form description="Travis CI build" \
$UPLOAD_URL)
+ printf "\033[33;1mThe response is\033[0m\n%s\n" "$response"
status_code=$(echo "$response" | sed -n '$p')
- if [ "$status_code" != "201" ]; then
+ # Coverity Scan used to respond with 201 on successfully receieving analysis results.
+ # Now for some reason it sends 200 and may change back in the foreseeable future.
+ # See https://github.com/pmem/pmdk/commit/7b103fd2dd54b2e5974f71fb65c81ab3713c12c5
+ if [ "$status_code" != "200" ]; then
TEXT=$(echo "$response" | sed '$d')
echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m"
exit 1
diff --git a/tools/find-double-newline.sh b/tools/find-double-newline.sh
new file mode 100755
index 0000000000..6a6790b4b2
--- /dev/null
+++ b/tools/find-double-newline.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1+
+
+TOP=`git rev-parse --show-toplevel`
+
+case "$1" in
+
+ recdiff)
+ if [ "$2" = "" ] ; then
+ DIR="$TOP"
+ else
+ DIR="$2"
+ fi
+
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \;
+ ;;
+
+ recpatch)
+ if [ "$2" = "" ] ; then
+ DIR="$TOP"
+ else
+ DIR="$2"
+ fi
+
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \;
+ ;;
+
+ diff)
+ T=`mktemp`
+ sed '/^$/N;/^\n$/D' < "$2" > "$T"
+ diff -u "$2" "$T"
+ rm -f "$T"
+ ;;
+
+ patch)
+ sed -i '/^$/N;/^\n$/D' "$2"
+ ;;
+
+ *)
+ echo "Expected recdiff|recpatch|diff|patch as verb." >&2
+ ;;
+esac
diff --git a/tools/find-tabs.sh b/tools/find-tabs.sh
new file mode 100755
index 0000000000..e32eac8f32
--- /dev/null
+++ b/tools/find-tabs.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1+
+
+TOP=`git rev-parse --show-toplevel`
+
+case "$1" in
+
+ recdiff)
+ if [ "$2" = "" ] ; then
+ DIR="$TOP"
+ else
+ DIR="$2"
+ fi
+
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \;
+ ;;
+
+ recpatch)
+ if [ "$2" = "" ] ; then
+ DIR="$TOP"
+ else
+ DIR="$2"
+ fi
+
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \;
+ ;;
+
+ diff)
+ T=`mktemp`
+ sed 's/\t/ /g' < "$2" > "$T"
+ diff -u "$2" "$T"
+ rm -f "$T"
+ ;;
+
+ patch)
+ sed -i 's/\t/ /g' "$2"
+ ;;
+
+ *)
+ echo "Expected recdiff|recpatch|diff|patch as verb." >&2
+ ;;
+esac
diff --git a/tools/gdb-sd_dump_hashmaps.py b/tools/gdb-sd_dump_hashmaps.py
index 7f5d31eca6..e6ddd14ea7 100644
--- a/tools/gdb-sd_dump_hashmaps.py
+++ b/tools/gdb-sd_dump_hashmaps.py
@@ -1,23 +1,6 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: LGPL-2.1+
-#
-# This file is part of systemd.
-#
-# Copyright 2014 Michal Schmidt
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
import gdb
diff --git a/tools/make-directive-index.py b/tools/make-directive-index.py
index fb2b0b7c6f..8b85ef40f3 100755
--- a/tools/make-directive-index.py
+++ b/tools/make-directive-index.py
@@ -1,23 +1,6 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: LGPL-2.1+
-#
-# This file is part of systemd.
-#
-# Copyright 2012-2013 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
import sys
import collections
@@ -31,15 +14,6 @@ TEMPLATE = '''\
<refentryinfo>
<title>systemd.directives</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/tools/make-man-index.py b/tools/make-man-index.py
index 5ff3616652..7ed98cb4e0 100755
--- a/tools/make-man-index.py
+++ b/tools/make-man-index.py
@@ -1,24 +1,6 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: LGPL-2.1+
-#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
import collections
import sys
@@ -33,15 +15,6 @@ TEMPLATE = '''\
<refentryinfo>
<title>systemd.index</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/tools/make-man-rules.py b/tools/make-man-rules.py
index 444d4a6ee4..42a48bc98c 100755
--- a/tools/make-man-rules.py
+++ b/tools/make-man-rules.py
@@ -1,23 +1,6 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: LGPL-2.1+
-#
-# This file is part of systemd.
-#
-# Copyright 2013, 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import collections
diff --git a/tools/meson-apply-m4.sh b/tools/meson-apply-m4.sh
new file mode 100755
index 0000000000..6abe177ac5
--- /dev/null
+++ b/tools/meson-apply-m4.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+set -eu
+
+CONFIG=$1
+TARGET=$2
+
+if [ $# -ne 2 ]; then
+ echo 'Invalid number of arguments.'
+ exit 1
+fi
+
+if [ ! -f $CONFIG ]; then
+ echo "$CONFIG not found."
+ exit 2
+fi
+
+if [ ! -f $TARGET ]; then
+ echo "$TARGET not found."
+ exit 3
+fi
+
+DEFINES=$(awk '$1 == "#define" && $3 == "1" { printf "-D%s ", $2 }' $CONFIG)
+
+m4 -P $DEFINES $TARGET
diff --git a/tools/meson-build.sh b/tools/meson-build.sh
index 302749d8ed..304a755676 100755
--- a/tools/meson-build.sh
+++ b/tools/meson-build.sh
@@ -7,4 +7,12 @@ target="$3"
options="$4"
[ -d "$dst" ] || meson "$src" "$dst" $options
-ninja -C "$dst" "$target"
+
+# Locate ninja binary, on CentOS 7 it is called ninja-build, so
+# use that name if available.
+ninja=ninja
+if which ninja-build >/dev/null 2>&1 ; then
+ ninja=ninja-build
+fi
+
+"$ninja" -C "$dst" "$target"
diff --git a/tools/meson-hwdb-update.sh b/tools/meson-hwdb-update.sh
index d4ec555beb..f9ef241719 100755
--- a/tools/meson-hwdb-update.sh
+++ b/tools/meson-hwdb-update.sh
@@ -4,9 +4,11 @@ set -eu
cd "$1"
unset permissive
-if [ "$2" = "-p" ]; then
+if [ "${2:-}" = "-p" ]; then
permissive=1
shift
+else
+ permissive=0
fi
if [ "${2:-}" != "-n" ]; then (
diff --git a/scripts/oss-fuzz.sh b/tools/oss-fuzz.sh
index 2c4e58e29d..200407fcca 100755
--- a/scripts/oss-fuzz.sh
+++ b/tools/oss-fuzz.sh
@@ -1,32 +1,24 @@
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Jonathan Rudenberg
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
set -ex
export LC_CTYPE=C.UTF-8
+export CC=${CC:-clang}
+export CXX=${CXX:-clang++}
+clang_version="$($CC --version | sed -nr 's/.*version ([^ ]+?) .*/\1/p' | sed -r 's/-$//')"
+
SANITIZER=${SANITIZER:-address -fsanitize-address-use-after-scope}
flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize-coverage=trace-pc-guard,trace-cmp"
+clang_lib="/usr/lib64/clang/${clang_version}/lib/linux"
+[ -d "$clang_lib" ] || clang_lib="/usr/lib/clang/${clang_version}/lib/linux"
+
export CFLAGS=${CFLAGS:-$flags}
export CXXFLAGS=${CXXFLAGS:-$flags}
-export CC=${CC:-clang}
-export CXX=${CXX:-clang++}
+export LDFLAGS=${LDFLAGS:--L${clang_lib}}
+
export WORK=${WORK:-$(pwd)}
export OUT=${OUT:-$(pwd)/out}
mkdir -p $OUT
@@ -52,8 +44,8 @@ df=$build/dns-fuzzing
git clone --depth 1 https://github.com/CZ-NIC/dns-fuzzing $df
zip -jqr $OUT/fuzz-dns-packet_seed_corpus.zip $df/packet
-mkdir -p $OUT/src/shared
-mv $build/src/shared/libsystemd-shared-*.so $OUT/src/shared
+# install the private shared library without executable permissions
+install -Dt $OUT/src/shared/ -m 0644 $build/src/shared/libsystemd-shared-*.so
find $build -maxdepth 1 -type f -executable -name "fuzz-*" -exec mv {} $OUT \;
cp src/fuzz/*.options $OUT
diff --git a/tools/xml_helper.py b/tools/xml_helper.py
index 47434c7156..19e343b4e3 100755
--- a/tools/xml_helper.py
+++ b/tools/xml_helper.py
@@ -1,23 +1,6 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
# SPDX-License-Identifier: LGPL-2.1+
-#
-# This file is part of systemd.
-#
-# Copyright 2012-2013 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
from lxml import etree as tree
diff --git a/travis-ci/Dockerfile b/travis-ci/Dockerfile
index 9554fcfc21..71dd07afe8 100644
--- a/travis-ci/Dockerfile
+++ b/travis-ci/Dockerfile
@@ -1,8 +1,7 @@
## Create Dockerfile that builds container suitable for systemd build
## This container runs as non-root user by deafult
-# Use the latest stable version of fedora
-FROM fedora:latest
+FROM fedora:27
# Demand the specification of non-root username
ARG DOCKER_USER
diff --git a/travis-ci/requirements.txt b/travis-ci/requirements.txt
index f2dbae4b38..9928e3fc87 100644
--- a/travis-ci/requirements.txt
+++ b/travis-ci/requirements.txt
@@ -1,3 +1,4 @@
dnf-plugins-core
meson
ninja-build
+python
diff --git a/travis-ci/scripts/build-docker-image.sh b/travis-ci/scripts/build-docker-image.sh
index 5d4333a95b..a18bf5fa85 100755
--- a/travis-ci/scripts/build-docker-image.sh
+++ b/travis-ci/scripts/build-docker-image.sh
@@ -1,14 +1,13 @@
#!/bin/bash
# Check environment
-[ -z "$DOCKER_REPOSITORY" ] && echo "ERROR: DOCKER_REPOSITORY must be set" && exit 1
[ -z "$TRAVIS_COMMIT" ] && echo "ERROR: TRAVIS_COMMIT must be set" && exit 1
# Build docker image
-echo -e "\n\033[33;1mBuilding docker image: $DOCKER_REPOSITORY:$TRAVIS_COMMIT.\033[0m"
+echo -e "\n\033[33;1mBuilding docker image: coverity-$TRAVIS_COMMIT.\033[0m"
docker build \
--build-arg DOCKER_USER=$USER \
--build-arg DOCKER_USER_UID=`id -u` \
--build-arg DOCKER_USER_GID=`id -g` \
---force-rm -t ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} --pull=true .
+--force-rm -t coverity-${TRAVIS_COMMIT} --pull=true .
diff --git a/travis-ci/tools/get-docker-remote.sh b/travis-ci/tools/get-docker-remote.sh
deleted file mode 100755
index 55bc29e7b1..0000000000
--- a/travis-ci/tools/get-docker-remote.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# Download and install docker-remote
-# Sets up venv folder
-# Notes: run with sudo command
-
-# Make sure python3 is installed and install git and virtual environment
-sudo apt-get update && sudo apt-get -y install python3 python3-pip git
-sudo apt-get install -y $(apt-cache search venv | cut -d' ' -f 1)
-
-# Get the tool from github and install it
-git clone https://github.com/CermakM/docker-remote.git
-
-# We need to setup virtual environment here to solve disable_warning issue
-python3 -m venv venv
-source venv/bin/activate
-
-pushd docker-remote
-pip install .
-popd
diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4
index 3c553240a2..3c553240a2 100644
--- a/units/console-getty.service.m4.in
+++ b/units/console-getty.service.m4
diff --git a/units/container-getty@.service.m4.in b/units/container-getty@.service.m4
index 087ab7f9b1..087ab7f9b1 100644
--- a/units/container-getty@.service.m4.in
+++ b/units/container-getty@.service.m4
diff --git a/units/meson.build b/units/meson.build
index 7f40464190..e4ac6ced64 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
units = [
['basic.target', ''],
@@ -36,6 +21,7 @@ units = [
['halt.target', ''],
['hibernate.target', 'ENABLE_HIBERNATE'],
['hybrid-sleep.target', 'ENABLE_HIBERNATE'],
+ ['suspend-then-hibernate.target', 'ENABLE_HIBERNATE'],
['initrd-fs.target', ''],
['initrd-root-device.target', ''],
['initrd-root-fs.target', ''],
@@ -91,6 +77,8 @@ units = [
['sysinit.target', ''],
['syslog.socket', ''],
['system-update.target', ''],
+ ['system-update-pre.target', ''],
+ ['system-update-cleanup.service', ''],
['systemd-ask-password-console.path', '',
'sysinit.target.wants/'],
['systemd-ask-password-wall.path', '',
@@ -139,7 +127,6 @@ in_units = [
['quotaon.service', 'ENABLE_QUOTACHECK'],
['rc-local.service', 'HAVE_SYSV_COMPAT'],
['rescue.service', ''],
- ['system-update-cleanup.service', ''],
['systemd-ask-password-console.service', ''],
['systemd-ask-password-wall.service', ''],
['systemd-backlight@.service', 'ENABLE_BACKLIGHT'],
@@ -155,6 +142,7 @@ in_units = [
['systemd-hibernate-resume@.service', 'ENABLE_HIBERNATE'],
['systemd-hibernate.service', 'ENABLE_HIBERNATE'],
['systemd-hybrid-sleep.service', 'ENABLE_HIBERNATE'],
+ ['systemd-suspend-then-hibernate.service', 'ENABLE_HIBERNATE'],
['systemd-hostnamed.service', 'ENABLE_HOSTNAMED',
'dbus-org.freedesktop.hostname1.service'],
['systemd-hwdb-update.service', 'ENABLE_HWDB',
@@ -188,6 +176,8 @@ in_units = [
['systemd-networkd-wait-online.service', 'ENABLE_NETWORKD',
join_paths(pkgsysconfdir, 'system/network-online.target.wants/')],
['systemd-nspawn@.service', ''],
+ ['systemd-portabled.service', 'ENABLE_PORTABLED',
+ 'dbus-org.freedesktop.portable1.service'],
['systemd-poweroff.service', ''],
['systemd-quotacheck.service', 'ENABLE_QUOTACHECK'],
['systemd-random-seed.service', 'ENABLE_RANDOMSEED',
@@ -208,6 +198,7 @@ in_units = [
'dbus-org.freedesktop.timedate1.service'],
['systemd-timesyncd.service', 'ENABLE_TIMESYNCD',
join_paths(pkgsysconfdir, 'system/sysinit.target.wants/')],
+ ['systemd-time-wait-sync.service', 'ENABLE_TIMESYNCD'],
['systemd-tmpfiles-clean.service', 'ENABLE_TMPFILES'],
['systemd-tmpfiles-setup-dev.service', 'ENABLE_TMPFILES',
'sysinit.target.wants/'],
@@ -228,32 +219,19 @@ in_units = [
'multi-user.target.wants/'],
['systemd-vconsole-setup.service', 'ENABLE_VCONSOLE'],
['systemd-volatile-root.service', ''],
+ ['user-runtime-dir@.service', ''],
['user@.service', ''],
]
m4_units = [
+ ['console-getty.service', ''],
+ ['container-getty@.service', ''],
['getty@.service', '',
'autovt@.service ' +
join_paths(pkgsysconfdir, 'system/getty.target.wants/getty@tty1.service')],
['serial-getty@.service', ''],
]
-m4_in_units = [
- ['console-getty.service', ''],
- ['container-getty@.service', ''],
-]
-
-foreach tuple : m4_in_units
- file = tuple[0]
-
- gen = configure_file(
- input : file + '.m4.in',
- output : file + '.m4',
- configuration : substs)
-
- m4_units += [[file, tuple.get(1, ''), tuple.get(2, ''), gen]]
-endforeach
-
foreach tuple : in_units
file = tuple[0]
@@ -295,7 +273,7 @@ foreach tuple : m4_units
file,
input : input,
output: file,
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : install,
install_dir : systemunitdir)
@@ -328,6 +306,9 @@ foreach tuple : units
endif
endforeach
+install_data('user-.slice.d/10-defaults.conf',
+ install_dir : systemunitdir + '/user-.slice.d')
+
############################################################
meson.add_install_script(meson_make_symlink,
diff --git a/units/suspend-then-hibernate.target b/units/suspend-then-hibernate.target
new file mode 100644
index 0000000000..999c0a9c86
--- /dev/null
+++ b/units/suspend-then-hibernate.target
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Suspend; Hibernate if not used for a period of time
+Documentation=man:systemd.special(7)
+DefaultDependencies=no
+Requires=systemd-suspend-then-hibernate.service
+After=systemd-suspend-then-hibernate.service
+StopWhenUnneeded=yes
diff --git a/units/system-update-cleanup.service.in b/units/system-update-cleanup.service
index 58baab3023..58baab3023 100644
--- a/units/system-update-cleanup.service.in
+++ b/units/system-update-cleanup.service
diff --git a/units/system-update-pre.target b/units/system-update-pre.target
new file mode 100644
index 0000000000..163b75c220
--- /dev/null
+++ b/units/system-update-pre.target
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Offline System Update (Pre)
+Documentation=man:systemd.offline-updates(7)
+Documentation=man:systemd.special(7) man:systemd-system-update-generator(8)
+RefuseManualStart=yes
+After=sysinit.target
diff --git a/units/system-update.target b/units/system-update.target
index c46bfe754a..29812edf92 100644
--- a/units/system-update.target
+++ b/units/system-update.target
@@ -12,6 +12,6 @@ Description=Offline System Update
Documentation=man:systemd.offline-updates(7)
Documentation=man:systemd.special(7) man:systemd-system-update-generator(8)
Requires=sysinit.target
-After=sysinit.target
+After=sysinit.target system-update-pre.target
AllowIsolate=yes
Wants=system-update-cleanup.service
diff --git a/units/systemd-coredump@.service.in b/units/systemd-coredump@.service.in
index 68fa55c807..215696ecd1 100644
--- a/units/systemd-coredump@.service.in
+++ b/units/systemd-coredump@.service.in
@@ -33,7 +33,8 @@ MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any
diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in
index 993134f3d6..da74b4fe8b 100644
--- a/units/systemd-hostnamed.service.in
+++ b/units/systemd-hostnamed.service.in
@@ -29,7 +29,8 @@ MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service sethostname
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any
diff --git a/units/systemd-importd.service.in b/units/systemd-importd.service.in
index 8e93c2d524..20704a8232 100644
--- a/units/systemd-importd.service.in
+++ b/units/systemd-importd.service.in
@@ -23,6 +23,7 @@ MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictNamespaces=net
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service @mount
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
index df76fe4226..52939e6820 100644
--- a/units/systemd-journald.service.in
+++ b/units/systemd-journald.service.in
@@ -29,7 +29,8 @@ MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any
diff --git a/units/systemd-localed.service.in b/units/systemd-localed.service.in
index ba8a08f3b4..a24e61a0cd 100644
--- a/units/systemd-localed.service.in
+++ b/units/systemd-localed.service.in
@@ -29,7 +29,8 @@ MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any
diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in
index 968b92a45c..5e090bcf23 100644
--- a/units/systemd-logind.service.in
+++ b/units/systemd-logind.service.in
@@ -29,8 +29,9 @@ CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CA
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictNamespaces=yes
-RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
+RestrictAddressFamilies=AF_UNIX AF_NETLINK
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any
diff --git a/units/systemd-machined.service.in b/units/systemd-machined.service.in
index f9e789db42..1200a90a61 100644
--- a/units/systemd-machined.service.in
+++ b/units/systemd-machined.service.in
@@ -23,7 +23,8 @@ CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_C
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service @mount
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any
diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in
index 63ee735415..371ab3a9cf 100644
--- a/units/systemd-networkd.service.in
+++ b/units/systemd-networkd.service.in
@@ -13,7 +13,7 @@ Documentation=man:systemd-networkd.service(8)
ConditionCapability=CAP_NET_ADMIN
DefaultDependencies=no
# systemd-udevd.service can be dropped once tuntap is moved to netlink
-After=systemd-udevd.service network-pre.target systemd-sysusers.service systemd-sysctl.service
+After=systemd-udevd.service network-pre.target systemd-sysctl.service
Before=network.target multi-user.target shutdown.target
Conflicts=shutdown.target
Wants=network.target
@@ -25,16 +25,18 @@ RestartSec=0
ExecStart=!!@rootlibexecdir@/systemd-networkd
WatchdogSec=3min
User=systemd-network
+DynamicUser=yes
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW
-ProtectSystem=strict
ProtectHome=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
+RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 AF_PACKET
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
RuntimeDirectory=systemd/netif
diff --git a/units/systemd-portabled.service.in b/units/systemd-portabled.service.in
new file mode 100644
index 0000000000..a868f61dba
--- /dev/null
+++ b/units/systemd-portabled.service.in
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Portable Service Manager
+Documentation=man:systemd-portabled.service(8)
+RequiresMountsFor=/var/lib/portables
+
+[Service]
+ExecStart=@rootlibexecdir@/systemd-portabled
+BusName=org.freedesktop.portable1
+WatchdogSec=3min
+CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD
+MemoryDenyWriteExecute=yes
+RestrictRealtime=yes
+RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+LockPersonality=yes
+IPAddressDeny=any
diff --git a/units/systemd-resolved.service.in b/units/systemd-resolved.service.in
index c4c7f1feef..9982ecebff 100644
--- a/units/systemd-resolved.service.in
+++ b/units/systemd-resolved.service.in
@@ -14,7 +14,7 @@ Documentation=https://www.freedesktop.org/wiki/Software/systemd/resolved
Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
DefaultDependencies=no
-After=systemd-sysusers.service systemd-networkd.service
+After=systemd-networkd.service
Before=network.target nss-lookup.target shutdown.target
Conflicts=shutdown.target
Wants=nss-lookup.target
@@ -26,19 +26,20 @@ RestartSec=0
ExecStart=!!@rootlibexecdir@/systemd-resolved
WatchdogSec=3min
User=systemd-resolve
+DynamicUser=yes
CapabilityBoundingSet=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
-PrivateTmp=yes
PrivateDevices=yes
-ProtectSystem=strict
ProtectHome=yes
ProtectControlGroups=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
+RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
RuntimeDirectory=systemd/resolve
diff --git a/units/systemd-suspend-then-hibernate.service.in b/units/systemd-suspend-then-hibernate.service.in
new file mode 100644
index 0000000000..5d6a582730
--- /dev/null
+++ b/units/systemd-suspend-then-hibernate.service.in
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Suspend; Hibernate if not used for a period of time
+Documentation=man:systemd-suspend.service(8)
+DefaultDependencies=no
+Requires=sleep.target
+After=sleep.target
+
+[Service]
+Type=oneshot
+ExecStart=@rootlibexecdir@/systemd-sleep suspend-then-hibernate
diff --git a/units/systemd-time-wait-sync.service.in b/units/systemd-time-wait-sync.service.in
new file mode 100644
index 0000000000..475182d6bc
--- /dev/null
+++ b/units/systemd-time-wait-sync.service.in
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=Wait Until Kernel Time Synchronized
+Documentation=man:systemd-time-wait-sync.service(8)
+
+# Note that this tool doesn't need CAP_SYS_TIME itself, but it's primary
+# usecase is to run in conjunction with a local NTP service such as
+# systemd-timesyncd.service, which is conditioned this way. There might be
+# niche usecases where running this service independently is desired, but let's
+# make this all "just work" for the general case, and leave it to local
+# modifications to make it work in the remaining cases.
+
+ConditionCapability=CAP_SYS_TIME
+ConditionVirtualization=!container
+
+DefaultDependencies=no
+Before=time-sync.target shutdown.target
+Wants=time-sync.target
+Conflicts=shutdown.target
+
+[Service]
+Type=oneshot
+ExecStart=@rootlibexecdir@/systemd-time-wait-sync
+TimeoutStartSec=infinity
+RemainAfterExit=yes
+
+[Install]
+WantedBy=sysinit.target
diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in
index cf13e40ced..906bb4326c 100644
--- a/units/systemd-timedated.service.in
+++ b/units/systemd-timedated.service.in
@@ -27,7 +27,8 @@ MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX
-SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallFilter=@system-service @clock
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any
diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in
index d3bc4e9841..4a490b6e16 100644
--- a/units/systemd-timesyncd.service.in
+++ b/units/systemd-timesyncd.service.in
@@ -13,7 +13,7 @@ Documentation=man:systemd-timesyncd.service(8)
ConditionCapability=CAP_SYS_TIME
ConditionVirtualization=!container
DefaultDependencies=no
-After=systemd-remount-fs.service systemd-sysusers.service
+After=systemd-remount-fs.service
Before=time-sync.target sysinit.target shutdown.target
Conflicts=shutdown.target
Wants=time-sync.target
@@ -37,10 +37,13 @@ MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
-SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+RuntimeDirectory=systemd/timesync
+SystemCallFilter=@system-service @clock
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
StateDirectory=systemd/timesync
[Install]
WantedBy=sysinit.target
+Alias=dbus-org.freedesktop.timesync1.service
diff --git a/units/systemd-udev-trigger.service.in b/units/systemd-udev-trigger.service.in
index 3cdde94446..b60204eccc 100644
--- a/units/systemd-udev-trigger.service.in
+++ b/units/systemd-udev-trigger.service.in
@@ -19,4 +19,5 @@ ConditionPathIsReadWrite=/sys
[Service]
Type=oneshot
RemainAfterExit=yes
-ExecStart=@rootbindir@/udevadm trigger --type=subsystems --action=add ; @rootbindir@/udevadm trigger --type=devices --action=add
+ExecStart=@rootbindir@/udevadm trigger --type=subsystems --action=add
+ExecStart=@rootbindir@/udevadm trigger --type=devices --action=add
diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in
index 8557522e7b..6a3814e5d9 100644
--- a/units/systemd-udevd.service.in
+++ b/units/systemd-udevd.service.in
@@ -25,10 +25,12 @@ ExecStart=@rootlibexecdir@/systemd-udevd
KillMode=mixed
WatchdogSec=3min
TasksMax=infinity
-MountFlags=slave
+PrivateMounts=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
+SystemCallFilter=@system-service @module @raw-io
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any
diff --git a/units/user-.slice.d/10-defaults.conf b/units/user-.slice.d/10-defaults.conf
new file mode 100644
index 0000000000..95ab11b30b
--- /dev/null
+++ b/units/user-.slice.d/10-defaults.conf
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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 Slice of UID %j
+After=systemd-user-sessions.service
+
+[Slice]
+TasksMax=33%
diff --git a/units/user-runtime-dir@.service.in b/units/user-runtime-dir@.service.in
new file mode 100644
index 0000000000..8c02beda3b
--- /dev/null
+++ b/units/user-runtime-dir@.service.in
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# 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=/run/user/%i mount wrapper
+StopWhenUnneeded=yes
+
+[Service]
+ExecStart=@rootlibexecdir@/systemd-user-runtime-dir start %i
+ExecStop=@rootlibexecdir@/systemd-user-runtime-dir stop %i
+RemainAfterExit=true
diff --git a/units/user/meson.build b/units/user/meson.build
index e463ae226c..b1c2e95597 100644
--- a/units/user/meson.build
+++ b/units/user/meson.build
@@ -1,19 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1+
-#
-# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
units = [
'basic.target',
diff --git a/units/user/systemd-exit.service.in b/units/user/systemd-exit.service.in
index 9ce6f1c2ac..d69273f6b3 100644
--- a/units/user/systemd-exit.service.in
+++ b/units/user/systemd-exit.service.in
@@ -16,4 +16,4 @@ After=shutdown.target
[Service]
Type=oneshot
-ExecStart=@KILL@ -s 58 $MANAGERPID
+ExecStart=@SYSTEMCTL@ --user --force exit
diff --git a/units/user@.service.in b/units/user@.service.in
index 372ffa56d3..b88108e1b7 100644
--- a/units/user@.service.in
+++ b/units/user@.service.in
@@ -10,6 +10,8 @@
[Unit]
Description=User Manager for UID %i
After=systemd-user-sessions.service
+After=user-runtime-dir@%i.service
+Requires=user-runtime-dir@%i.service
[Service]
User=%i